问题

最近我在处理一批数据,用多线程来处理,我想知道大概多久能处理完。比如我先用多线程处理 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

可以看到总用时比花费最长时间的线程任务时间多一点,随着并发量越大,达到可同时并发执行的线程最大数后,用时会越久。