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());
我正在尝试对上面的代码运行一些性能测试。我尝试在不同的executor
上使用相同的Runnable
并测量时间。但它不太有效。第一个“总时间”不正确,以毫秒为单位。
我想在第一个循环上打印经过的时间,然后打印第二个循环。不确定我如何等待执行程序完成第一个然后重新启动执行程序。
完成这项工作的正确方法是什么?
答案 0 :(得分:1)
首先,awaitTermination
将block,直到所有任务终止。在等待潜在70 years之后使用while循环检查是否有任何特殊原因?
无论如何,为了回答你的问题,为了等待第一次运行完成,你应该使用CountDownLatch
来表示每个线程的完成并在主线程中等待它们直到它们完成。您还可以使用CyclicBarrier
等待所有线程准备好开始计时之前,如下所示:
...
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();
...
我将sw.start()
移动到for循环的开头,以避免测量设置的对象分配开销(可能无论如何都不会被测量,因为它以ms为单位)。
您还可以重置两个并发类以无限次地运行。
答案 1 :(得分:0)
您现在正在做的是:
你不是在等待他们完成第二次循环。
这是你可以做的解决这个问题的方法。
在SingleConnectionRunnable中创建一个回调方法。
此方法将在此runnable的最后一个点(当你终止它时)被调用并被启动循环的类捕获(这不是问题中的方法,但没关系)。
在此回调方法中,您可以跟踪它的调用次数。
当打印秒表时间被称为MYTHREAD次数时。
现在您知道在所有已启动的线程完成之前需要多长时间。