Java线程池之主线程等待子线程完成

在开发中处理一些问题会使用多线程提升处理效率,但是又想有一个最终的结果输出来确认所有任务已经全部处理完成,此时就需要主线程等待所有子线程处理完成之后再输出结果。本次提供两种简单明了的Demo用于记录与分享。

  1. CountDownLatch 计数器方案

public void countDownLatchDemo() {
    int count = 10;
    CountDownLatch latch = new CountDownLatch(count);
    ExecutorService executorService = Executors.newFixedThreadPool(2);
    for (int i = 0; i < count; i++) {
        int finalI = i;
        executorService.submit(() -> {
            try {
                System.out.println(finalI + "执行了, 子线程:" + Thread.currentThread().getName());
            } finally {
                latch.countDown();
            }
        });
    }
    try {
        latch.await();
    } catch (Exception e) {
        e.printStackTrace();
    }
    executorService.shutdown();
    System.out.println("线程池已关闭,主线程完成");
}

计数器方案需要处理前就清楚自己要处理的任务数,每个子线程处理完计数器都减少一次,直到计数器的值为零,主线程就不会被阻塞了,此时就可以进行最后的信息输出。

计数器方案当然也可以直接使用AtomicInteger 自减处理。

  1. Future 线程接口回调方案

public void futureDemo() {
    ExecutorService executorService = Executors.newFixedThreadPool(2);
    List<Future> futureList = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        int finalI = i;
        Future<?> submit = executorService.submit(() -> System.out.println(finalI + "执行了, 子线程:" + Thread.currentThread().getName()));
        futureList.add(submit);
    }
    try {
        while (true) {
            boolean out = false;
            for (Future future : futureList) {
                out = future.isDone();
                if (!out) break;
            }
            if (out) break;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    executorService.shutdown();
    System.out.println("线程池已关闭,主线程完成");
}

Future 的方案是通过循环的确认所有的Future对象是否已经全部结束,如果已经全部结束,主线程输出最终结果信息,此方案会有额外的消耗,如果增加时间间隔的话,在计时上会不是很准确。


版权声明:本文为cymen原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。