问题:使用线程池来进行多线程操作的话,怎么实现让主线程等待其他线程的任务执行完后再进行接下来的操作。
解决方案:线程池+CountDownLatch
demo:
public void testLock(){
//模拟并发
List<Integer> ids = new ArrayList<>();
ids.add(1);
ids.add(2);
ids.add(3);
ids.add(4);
ids.add(5);
ids.add(6);
ids.add(7);
ids.add(8);
//使用锁,用于等待结果全部执行完
CountDownLatch countDownLatch = new CountDownLatch(ids.size());
ExecutorService executor = Executors.newFixedThreadPool(50);
executor.execute(() -> {
//多线程处理业务
try {
// 模拟业务
Thread.sleep(1000);
} catch (Exception e) {
} finally {
//放在finally保证不管结果是否异常都会减,避免锁死
countDownLatch.countDown();
}
});
try {
//主线程阻塞等待锁
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
CountDownLatch原理:
CountDownLatch 是通过一个计数器来实现的,当我们在 new 一个 CountDownLatch 对象的时候,需要带入该计数器值,该值就表示了线程的数量。
每当一个线程完成自己的任务后,计数器的值就会减 1 。当计数器的值变为0时,就表示所有的线程均已经完成了任务,然后就可以恢复等待的线程继续执行了。
由于调用了 countDown方法,所以在当前计数到达0之前,await方法会一直受阻塞;当计数到达0时会唤醒await方法阻塞的线程执行。