我从我的代码开始多个线程(大约1000个)。它们是从while循环调用的Runnable线程。如何计算所有线程完成执行所需的总时间?
此外,我正在打开一个数据库连接并且有一组查询,我正在为这些线程启动这些线程(1个查询的1个线程)。我什么时候关闭连接?
答案 0 :(得分:8)
我会使用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);
完成连接后关闭连接。对于资源的创建者来说,关闭它也是一种常见的模式。例如如果主线程创建了连接,它可能会在所有线程完成后关闭。
答案 1 :(得分:3)
使用像提到的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();
}
答案 2 :(得分:1)
你需要另一个线程等待这1000个线程完成它们的工作,你可以用CountDownLatch做到这一点,但你需要知道你拥有的线程的确切数量 - 在你的情况下为1000。
这样的事情:
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));
}
}
答案 3 :(得分:1)
答案 4 :(得分:1)
通常,您无法准确测量时间执行,因为上下文切换。如果你有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));
}
答案 5 :(得分:0)
可能最简单的方法是将这些线程放在一个列表上并检查它们中是否有任何一个是活着的(Thread.isAlive()方法),将死掉的列表从列表中删除。重复直到列表为空。缺点是它会给你一些误差的时间。
另一个解决方案是将'父'控制器注入这些线程,然后在完成时让它们报告。同样的逻辑适用 - 我们可以从列表(或其他类型的集合)中提取完成的线程,直到我们的列表为空。这种方法更精确,但需要在线程中添加额外的逻辑。