问题
最近我在处理一批数据,用多线程来处理,我想知道大概多久能处理完。比如我先用多线程处理 100 条数据,统计下用时,然后根据总的数据量就可以大概估算出处理完这批数据要多久。
使用 CountDownLatch 计时
思路:用两个 CountDownLatch 倒计时锁:开始计时锁,任务结束计时锁。开始计时锁在子线程任务开始时通过 await() 阻塞所有子线程,然后在主线程中通过 CountDownLatch 控制所有子线程同时开始获取开始时间;任务结束计时锁 CountDownLatch 在每个子线程执行完后都 countDown 一次,直到所有子线程执行完,主线程开始记录所有任务执行结束时间。
示例代码
/**
* ClassName: ThreadTiming <br/>
* Function: 计算多个线程任务执行完后的用时<br/>
*
* @author gary.liu
* @date 2017/6/24
*/
public class ThreadTiming {
private int nThread;
private CountDownLatch startGate;
private CountDownLatch endGate;
public ThreadTiming(int nThread, CountDownLatch startGate, CountDownLatch endGate) {
this.nThread = nThread;
this.startGate = startGate;
this.endGate = endGate;
}
class worker implements Runnable {
public void run() {
try {
startGate.await();
Random random = new Random();
int num = random.nextInt(500) + 500;
System.out.println(Thread.currentThread().getName() + " start and sleep: " + num + "ms");
Thread.sleep(num);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
endGate.countDown();
}
}
}
public long timeTasks() {
for(int i = 0; i < nThread; i++){
Thread thread = new Thread(new worker());
thread.start();
}
long start = System.currentTimeMillis();
//所有阻塞的任务同时开始
startGate.countDown();
try {
//主线程阻塞,等待其他所有 worker 线程完成后再执行
endGate.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("用时: " + (end - start) + "ms");
return end - start;
}
public static void main(String[] args) {
int nThread = 5;
CountDownLatch startGate = new CountDownLatch(1);
CountDownLatch endGate = new CountDownLatch(nThread);
new ThreadTiming(nThread, startGate, endGate).timeTasks();
}
}
运行结果
Thread-4 start and sleep: 897ms Thread-0 start and sleep: 811ms Thread-2 start and sleep: 678ms Thread-3 start and sleep: 582ms Thread-1 start and sleep: 576ms 用时: 903ms
可以看到总用时比花费最长时间的线程任务时间多一点,随着并发量越大,达到可同时并发执行的线程最大数后,用时会越久。