2013-04-29 119 views
3

我試圖設置生產者/消費者使用硒webdriver作爲查詢/瀏覽器。我如何成功在Java中多線程Selenium服務器?

雖然運行下面的代碼,但並不是所有查詢都是實際輸入的,即使輸出顯示它們是。有些查詢也可能翻倍(即「魚」變成「FisFishh」)。

APP
public class App { 

    public static void main(String[] args) { 

     DriverHashMap.init(); 

     Executor exec = new Executor(); 

     // Add queries to list 
     Query query = new Query(exec); 
     query.addQuery("Cats"); 
     query.addQuery("Dogs"); 
     query.addQuery("Fish"); 
     // query.addQuery("Bats"); 
     // query.addQuery("Rats"); 
     // query.addQuery("Geese"); 

     ExecutorService threadPool = Executors.newFixedThreadPool(4); 

     // Submit queries to pool 
     Future queryStatus = threadPool.submit(query); 

     // Start browsers 
     threadPool.execute(new Browser("1", exec)); 
     threadPool.execute(new Browser("2", exec)); 

     // this will wait for the producer to finish its execution. 
     try { 
      queryStatus.get(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } catch (ExecutionException e) { 
      e.printStackTrace(); 
     } 

     // Wait for pool to finish 
     threadPool.shutdown(); 

    } 
} 

BROWSER
public class Browser implements Runnable { 
    private String name; 
    private Executor exec; 

    private static WebDriver driver; 
    private static String baseURL = "http://www.google.com"; 
    private static String query; 

    public Browser(String name, Executor exec) { 

     synchronized (this) { 
      this.name = name; 
      this.exec = exec; 

      System.out.println("\tStart Browser-" + this.name); 
      driver = new FirefoxDriver(); 
      // Wait up to 30 seconds for a response 
      driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); 

      DriverHashMap.addDriver(name, driver); 
      System.out.println("\tAdded Browser-" + name + " to hashmap"); 
     } 

    } 

    private void enterQuery() { 

     synchronized (this) { 
      // Get driver for this browser 
      driver = DriverHashMap.getDriver(this.name); 
      System.out.println("Browser " + this.name 
        + " entering query from executor: " + query); 

      // Search field qbqfq 
      driver.findElement(By.id("gbqfq")).clear(); 

      // Enter query 
      driver.findElement(By.id("gbqfq")).sendKeys(query); 

      // Click search button 
      driver.findElement(By.id("gbqfb")).click(); 
     } 

    } 

    public void run() { 
     try { 

      synchronized (this) { 
       // Receive first query 
       driver = DriverHashMap.getDriver(this.name); 
       query = exec.get(); 
       System.out.println("Browser " + this.name 
         + "\n\rReceived first query from executor: " + query); 
      } 

      do { 

       synchronized (this) { 
        // Process query 
        driver = DriverHashMap.getDriver(this.name); 
        driver.get(baseURL); 
        enterQuery(); 
       } 

       synchronized (this) { 
        // Receive next query 
        query = exec.get(); 
        driver = DriverHashMap.getDriver(this.name); 
        System.out.println("Browser " + this.name 
          + "\n\rReceived new query from executor: " + query); 
       } 

      } while (query != null); 

      // Close this browser 
      synchronized (this) { 
       driver = DriverHashMap.getDriver(this.name); 
       System.out.println("Browser " + this.name 
         + " finished its job; terminating."); 

       driver.close(); 
      } 

     } catch (InterruptedException ex) { 
      ex.printStackTrace(); 
     } 
    } 

} 

QUERY
public class Query implements Runnable { 
    private Executor exec; 
    private List<String> queries = new ArrayList<String>(); 

    public Query(Executor exec) { 
     this.exec = exec; 
    } 

    public void addQuery(String query) { 
     System.out.println("Adding " + query + " to queries"); 
     queries.add(query); 
    } 

    public void run() { 

     Iterator it = queries.iterator(); 
     String currQuery = new String(); 

     try { 
      while(it.hasNext()) { 
       currQuery = (String)it.next(); 
       System.out.println("Adding " + currQuery + " to Executor"); 
       exec.put(currQuery); 
      } 

      this.exec.continueProducing = Boolean.FALSE; 
      System.out.println("Query has finished its job; terminating."); 
     } catch (InterruptedException ex) { 
      ex.printStackTrace(); 
     } 

    } 
} 

EXECUTOR
public class Executor { 
    public ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<String>(
      100); 
    public Boolean continueProducing = Boolean.TRUE; 

    public void put(String query) throws InterruptedException { 
     this.queue.put(query); 
    } 

    public String get() throws InterruptedException { 
     return this.queue.poll(1, TimeUnit.SECONDS); 
    } 
} 

回答

2

W¯¯ ebdriver本身不是線程安全的。嘗試將其包裝成ThreadLocal

這在類似的情況下幫了我很多。

+0

我從來沒有聽說過ThreadLocal,感謝你的鏈接,我會看看一些例子。 – Ergosphere 2013-05-01 00:30:06