java 如何计算多个线程完成执行所需的总时间?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11859534/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to calculate the total time it takes for multiple threads to finish executing?
提问by user1583803
I am starting multiple threads(around 1000) from my code. They are Runnable threads called from a while loop. How do I calculate the total time taken for all threads to finish executing?
我从我的代码中启动了多个线程(大约 1000 个)。它们是从 while 循环调用的 Runnable 线程。如何计算所有线程完成执行所需的总时间?
Also I am opening a DB Connection and have a set of queries for which I am starting these threads(1 thread for 1 query). When do I close the connection?
此外,我正在打开一个数据库连接并有一组查询,我正在为其启动这些线程(1 个线程用于 1 个查询)。我什么时候关闭连接?
回答by Peter Lawrey
I would use an ExecutorService
我会使用 ExecutorService
long start = System.nanoTime();
ExecutorService service = Executors.newWhatEverPool();
for(loop)
service.submit(new MyRunnable());
service.shutdown();
service.awaitTermination(1, TimeUnit.HOUR); // or longer.
long time = System.nanoTime() - start;
System.out.printf("Tasks took %.3f ms to run%n", time/1e6);
Close the connection when you have finished with it. It is a common pattern for the creator of a resource to also close it. e.g. If the main thread creates the connection, it could close after all the threads have finished.
完成后关闭连接。资源的创建者也关闭它是一种常见的模式。例如,如果主线程创建连接,它可能会在所有线程完成后关闭。
回答by gresdiplitude
Use a CountDownLatch like mentioned here.
使用这里提到的 CountDownLatch 。
public class StopLatchedThread extends Thread {
private final CountDownLatch stopLatch;
public StopLatchedThread(CountDownLatch stopLatch) {
this.stopLatch = stopLatch;
}
public void run() {
try {
// perform interesting task
} finally {
stopLatch.countDown();
}
}
}
public void performParallelTask() throws InterruptedException {
CountDownLatch cdl = new CountDownLatch(10);
for (int i = 0; i < 10; i++) {
Thread t = new StopLatchedThread(cdl);
t.start();
}
cdl.await();
}
回答by Eugene
You need another Thread to wait until these 1000 Threads have finished their work, you can do that with a CountDownLatch, but you need to know the exact number of Threads that you have - 1000 in your case.
您需要另一个线程来等待这 1000 个线程完成它们的工作,您可以使用 CountDownLatch 来做到这一点,但是您需要知道您拥有的线程的确切数量 - 在您的情况下为 1000。
Something like this:
像这样的东西:
public class LatchTest {
public static void main(String[] args) throws Exception {
final CountDownLatch latch = new CountDownLatch(100);
long startTime = System.nanoTime();
for(int i=0;i<100;++i){
new Thread(new Runnable() {
public void run() {
//Simulate some work
latch.countDown();
}).start();
}
// Main Thread will wait for all Threads to finish
latch.await();
long finishTime = System.nanoTime();
System.out.println("Have passed : " + (finishTime - startTime));
}
}
回答by Brian Agnew
回答by Taky
In general you cannot measure time execution exactly because context switching. If you have 1000 threads it is produce significant impact to all time measuring. Nevertheless if you may omit high exactness of time measuring you may use CountDownLautching primitive to synchronizing thread starting and thread finishing:
通常,由于上下文切换,您无法准确测量时间执行。如果您有 1000 个线程,则会对所有时间测量产生重大影响。不过,如果您可能会忽略时间测量的高精确度,您可以使用 CountDownLautching 原语来同步线程启动和线程完成:
public static void main( String[] args ) throws InterruptedException {
final int THREAD_COUNT = 10000;
long startTime;
long endTime;
final CountDownLatch startBarierr = new CountDownLatch(THREAD_COUNT + 1);
final CountDownLatch finishBarierr = new CountDownLatch(THREAD_COUNT);
for (int i = 0; i < THREAD_COUNT; i++){
final int iterationIndex = i;
new Thread(new Runnable() {
@Override
public void run() {
startBarierr.countDown();
System.out.println("Thread " + iterationIndex + " started");
try {
startBarierr.await();
//do some work in separate thread
int iterationCount = (int)(0.8*Integer.MAX_VALUE);
for(int i = 0; i < iterationCount; i++){
}
System.out.println("Thread " + iterationIndex + " finished");
finishBarierr.countDown(); //current thread finished, send mark
} catch (InterruptedException e) {
throw new AssertionError("Unexpected thread interrupting");
}
}
}).start();
}
startBarierr.countDown();
startBarierr.await(); //await start for all thread
startTime = System.currentTimeMillis(); //and note time
finishBarierr.await(); //wait each thread
endTime = System.currentTimeMillis(); //note finish time
System.out.println("Time(ms) - " + (endTime - startTime));
}
回答by jderda
Probably the easiest way is to put those Threads on a list and checking in intervals whether any of them is alive (Thread.isAlive() method), taking the dead ones off the list. Repeat until list is empty. Downside is that it'll give you the time with some error margin.
可能最简单的方法是将这些线程放在一个列表中,并每隔一段时间检查它们中的任何一个是否还活着(Thread.isAlive() 方法),将死的从列表中删除。重复直到列表为空。缺点是它会给你一些误差的时间。
The other solution is to inject 'parent' controller into those threads, then make them report back upon finishing. The same logic applies - we can pull a finished thread from list (or some other kind of set) until our list is empty. This method is more precise, but requires adding additional logic into threads.
另一种解决方案是将“父”控制器注入这些线程,然后让它们在完成后报告。同样的逻辑适用——我们可以从列表(或其他类型的集合)中拉出一个完成的线程,直到我们的列表为空。这种方法更精确,但需要在线程中添加额外的逻辑。