Java 正在等待池完成线程 StopWatch sw=新秒表(); sw.start(); ExecutorService executor=Executors.newFixedThreadPool(MYTHREADS); for(int i=0;i
我正在尝试对上面的代码运行一些性能测试。我试图在不同的Java 正在等待池完成线程 StopWatch sw=新秒表(); sw.start(); ExecutorService executor=Executors.newFixedThreadPool(MYTHREADS); for(int i=0;i,java,multithreading,executorservice,Java,Multithreading,Executorservice,我正在尝试对上面的代码运行一些性能测试。我试图在不同的Runnable上使用相同的executor,并测量时间。但这不太管用。第一个“总时间”不正确,以毫秒为单位 我想在第一个循环上打印经过的时间,然后打印第二个循环。不知道如何等待executor完成第一个,然后重新启动executor 完成此任务的正确方法是什么?您现在要做的是: 启动秒表 开始几个线程 看秒表 您不会像第二个循环那样等待它们完成 这就是你能做的来解决这个问题 在SingleConnectionRunnable中创建回调方法
Runnable
上使用相同的executor
,并测量时间。但这不太管用。第一个“总时间”不正确,以毫秒为单位
我想在第一个循环上打印经过的时间,然后打印第二个循环。不知道如何等待executor完成第一个,然后重新启动executor
完成此任务的正确方法是什么?您现在要做的是:
这就是你能做的来解决这个问题 在SingleConnectionRunnable中创建回调方法 这个方法将在这个runnable的最后一点(当您终止它时)被调用,并被启动循环的类捕获(这不是问题中的方法,但这很好) 在这个回调方法中,您可以跟踪它被调用的次数 当它被称为MYTHREAD时,读取您打印秒表时间的次数
现在您知道了完成所有启动的线程需要多长时间。首先,
等待终止
直到所有任务终止。在等待之后使用while循环检查有什么特殊原因吗
无论如何,为了回答您的问题,为了等待第一次运行完成,您应该使用倒计时闩锁
来表示每个线程完成,并在主线程中等待它们完成。您还可以使用CyclicBarrier
等待所有线程准备就绪后再开始计时,如下所示:
StopWatch sw = new StopWatch();
sw.start();
ExecutorService executor = Executors.newFixedThreadPool(MYTHREADS);
for (int i = 0; i < MYTHREADS; i++) {
Runnable worker = new SingleConnectionRunnable();
executor.execute(worker);
}
sw.stop();
System.out.println("total time"+sw.toString());
sw.reset();
sw.start();
for (int i = 0; i < MYTHREADS; i++) {
Runnable worker2 = new PooledConnectionRunnable();
executor.execute(worker2);
}
executor.shutdown();
executor.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);
while (!executor.isTerminated()) {
}
sw.stop();
System.out.println("total time"+sw.toString());
我将sw.start()
移动到for循环的开头,以避免测量设置的对象分配开销(可能不会以毫秒为单位进行测量)
您还可以重置这两个并发类以无限次运行。如果OP仍然担心
awaitTermination
在将调用更改为awaitTermination(Long.MAX\u VALUE,TimeUnit.DAYS)后,在68年内执行器服务未完成的情况下返回,则可能会出现重复的情况。
,它将一直等到世界末日,或者换句话说,,而(!executor.isTerminated()){}
可能会由于25269512429739111年内的硬件故障而错误终止。除此之外,倒计时锁存器
可能有些过分,因为每个执行器服务
都提供了invokeAll
,当所有作业完成时返回。不过,您必须使用Callable
。@Holger我认为必须提供一个列表会使代码更加复杂,尽管如果OP已经使用Callable,那么我认为应该使用invokeAll
。。。
...
CountDownLatch latch = new CountDownLatch(MYTHREADS);
CyclicBarrier cb = new CyclicBarrier(MYTHREADS, new Runnable() {
@Override public void run() {
sw.start();
}
});
for (...) {
Runnable worker = ...
executor.execute(new Runnable() {
@Override public void run() {
try {
cb.await();
} catch (Exception e) {
throw new RuntimeException(e);
}
worker.run();
latch.countDown();
}
});
}
latch.await();
sw.stop();
...