簡単なSeleniumアクセス制御スレッドプール


構想:頻繁にphantomJSプロセスをスイッチするのは比較的に資源を消耗するので、1つのスレッドプールを維持してアクセスを制御してメモリの消耗を減らす必要がある
1.カスタムアクションCustomActionインタフェース
public interface CustomAction {
    String action(WebDriver webDriver);
}

2.WebDriverPoolプール
public class WebDriverPool {

    //      
    private static final int MAX_COUNT = 15;
    //       
    private Semaphore semaphore = new Semaphore(MAX_COUNT);
    // webDriver 
    private WebDriver[] webDrivers = new WebDriver[MAX_COUNT];

    private boolean[] driverFlag = new boolean[MAX_COUNT];

    private Lock lockDrivers = new ReentrantLock();

    //phantomjs  
    private final String JS_BIN = "f:/phantomjs";

    public WebDriverPool() {
        System.setProperty("phantomjs.binary.path", JS_BIN);
        for (int i = 0; i < MAX_COUNT; i++) {
            driverFlag[i] = true;
        }
        //           
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            for (WebDriver webDriver : webDrivers) {
                if (webDriver != null) {
                    webDriver.quit();
                }
            }
        }));
    }

    /**
     *       PhantomJSDriver
     */
    private WebDriver defaultDriver() {
        DesiredCapabilities cap = DesiredCapabilities.phantomjs();
        //        
        List cmdList = new ArrayList<>();
        //     
        cmdList.add("--load-images=false");
        //     
        cmdList.add("--disk-cache=true");
        cap.setCapability("phantomjs.cli.args", cmdList);
        return new PhantomJSDriver(cap);
    }

    /**
     *        driver   
     *
     * @return      driver   
     */
    private int freeDriverIndex() {
        int ret = -1;
        try {
            lockDrivers.lock();
            for (int i = 0; i < driverFlag.length; i++) {
                if (driverFlag[i]) {
                    driverFlag[i] = false;
                    ret = i;
                    break;
                }
            }
            if (ret != -1) {
                if (webDrivers[ret] == null) {
                    webDrivers[ret] = defaultDriver();
                }
            }
        } finally {
            lockDrivers.unlock();
        }
        return ret;
    }

    /**
     *     js     html
     */
    public String customJs(CustomAction action) {
        String html = "";
        try {
            semaphore.acquire();
            int index = freeDriverIndex();
            //        
            html = action.action(webDrivers[index]);
            driverFlag[index] = true;
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            semaphore.release();
        }
        return html;
    }

}

欠点:
1.実行時にスレッドプール内のリソースを自由に伸縮できない、つまり、アイドル時にプール内のリソースを破棄できないためメモリ消費を減らすことができず、実行時にうまく伸縮できない
2.PhantomJSプロセスごとに1つのウィンドウしか実行されていないので、無駄です.PhantomJsDriverServiceとRemoteWebDriverを組み合わせることで、より高い同時実行をサポートできます.
3.apache commons pool 2による実装を考える