Java多线程——获取多个线程任务执行完的时间

问题

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

可以看到总用时比花费最长时间的线程任务时间多一点,随着并发量越大,达到可同时并发执行的线程最大数后,用时会越久。下面线程池的例子,限制了并发线程数后,可以明显的看到这一点。

用栅栏 CyclicBarrier 应该也是可以实现的,也可以和wait()、notifyAll() 混用来实现 ,这里就不在具体展开了。

使用线程池中方法计时

线程池中提供了监控线程池运行的一些方法,这里通过线程池的 isTerminated() 方法不断检测,线程池中的任务是否都执行完成了,来获取所有任务结束时间。

示例代码

public class ExecuteOrderPractice { 

    public void orderPractice(){
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        long start = System.currentTimeMillis();
        for(int i = 0; i < 5; i++){
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    try{
                        Thread.sleep(1000);
                        System.out.println(Thread.currentThread().getName() + " do something");
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }
                }
            });
        }

        executorService.shutdown();

        while(true){
            if(executorService.isTerminated()){
                //System.out.println("Finally do something ");
                long end = System.currentTimeMillis();
                System.out.println("用时: " + (end - start) + "ms");
                break;
            }

        }
    }

    public static void main(String[] args){
        new ExecuteOrderPractice().orderPractice();

    }
}

运行结果

pool-1-thread-1 do something
pool-1-thread-3 do something
pool-1-thread-2 do something
pool-1-thread-1 do something
pool-1-thread-3 do something
用时: 2010ms

参考资料

《Java 并发编程实战》

    原文作者:gary-liu
    原文地址: https://blog.csdn.net/lzx_2011/article/details/73694477
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞