Java 多线程/并发运行selenium Windows
我目前正在进行一个项目,使用selenium和Java 多线程/并发运行selenium Windows,java,multithreading,selenium,Java,Multithreading,Selenium,我目前正在进行一个项目,使用selenium和phantomJS 我写的项目运行良好,但问题是它非常慢,所以我想我可能会在其中引入多线程 我知道selenium不是多线程安全的,每个线程都应该有自己的webdriver(为了清楚起见) 重点是: 我有一个包含url中使用的对象的数组(只是其中的一部分) 目前,我正在为对象运行for循环,并将驱动程序导航到给定的xpath,获取数据并初始化对象。为了更快,我想创建4个线程,每个线程应该: 初始化新的web驱动程序 从列表中获取尚未使用的项 在此对象
phantomJS
我写的项目运行良好,但问题是它非常慢,所以我想我可能会在其中引入多线程
我知道selenium不是多线程安全的,每个线程都应该有自己的webdriver(为了清楚起见)
重点是:
我有一个包含url中使用的对象的数组(只是其中的一部分)
目前,我正在为对象运行for循环,并将驱动程序导航到给定的xpath,获取数据并初始化对象。为了更快,我想创建4个线程,每个线程应该:
public static class MyThread implements Runnable {
private Objectx object
private WebDriver driver;
public MyThread(Objectx object){
this.object = object;
}
@Override
public void run() {
driver = driverSettings(driver);
driver.navigate().to("website" + object.getNumber + ".html");
function1(object);
function2(object);
}
}
在主要方法中:
ExecutorService executor = Executors.newFixedThreadPool(4);
现在我有了对象列表
private static List<Objectx> listOfObjects = new ArrayList<Objectx>();
或者如何添加所有对象以创建可运行列表?以下是基本步骤 1) 创建一个线程池。线程的数量不取决于要处理的对象的大小。例如,您可以创建一个包含4个线程的池来处理250个对象 2) 创建线程时,将对象列表传递给其构造函数 3) 每个线程从列表中获取下一个对象并将其从列表中删除。您可以使用队列而不是列表 4) 重要提示:应该同步对列表(队列)的访问,以便一次只有一个线程可以修改它。最简单的方法之一是使用ConcurrentLinkedQueue 5) run()中的每个线程从列表(从队列)中检索下一个任务,处理它,检索下一个任务。如果没有其他任务,线程将退出其run()方法 更新1:(问题更新后) “MyThread”这个名称是误导性的,因为它不是一个线程。我建议你根据它的功能来命名它,比如“WebSiteParser”。但对于功能结果来说,这并不重要:) 创建runnable实例时,应将其提交给执行器。它将根据池中的线程数执行它们 更新2:
关于Web驱动程序的重用:如果您使用ExecutorService,那么我建议您提前创建Web驱动程序,将它们放入堆栈或队列中。当一个线程开始它的任务时,它应该从这个堆栈或队列中获取一个Web驱动程序。当它完成任务时,应该将其Web驱动程序放回堆栈或队列。再次确保对该堆栈或队列的访问是线程安全的。解释您希望使用两个线程更快的部分,以及为什么您认为它会更快。@mentalurg,它会更快,因为我可以同时打开多个浏览器窗口并使用它们。因此每个线程都有自己的任务。那到底是什么问题?是的。问题是我应该使用什么以及如何准确地使用它。如何创建给定数量的线程并在给定的对象列表上执行它们。我设法让它在线程上运行(如果我有fx4个对象,它会创建4个线程,但问题是如果我有250个对象),你是否试图以并行模式运行测试脚本以节省时间?我已经编辑了这个问题,你介意看一看吗?太棒了!我设法做到了。但我还有一个问题。每当我调用run命令时,我都会创建新的驱动程序。是否可以列出这些线程,并且每个线程都应该获得“免费”驱动程序?或者每个根目录在一生中保留相同的驱动程序?
For (Objectx object : listOfObjects){
Runnabble object.getNumber() = new MyThread(object).start()
}