CountDownLatch定义
CountDownLatch是一个同步工具类,CountDownLatch这个类能够使一个线程等待其他线程完成各自的工作后再执行。
CountDownLatch是在java1.5被引入的,跟它一起被引入的并发工具类还有CyclicBarrier、Semaphore、ConcurrentHashMap和阻塞队列BlockingQueue。
CountDownLatch作用
CountDownLatch的作用很简单,就是一个或者一组线程在开始执行操作之前,必须要等到其他线程执行完才可以。
例如:应用程序的主线程,希望在负责启动框架服务的线程,启动所有的框架服务之后,最后再执行。
除了刚提到的技术场景,生活中场景也是非常多的,比如:在考试的时候,老师必须要等到所有人交了试卷才可以走。
CountDownLatch实现原理
CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。
每当一个线程完成了自己的任务后,计数器的值就会减1,当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。
如下图所示:
整个的实现步骤,大致可以分为如下3步:
第一步:初始计数器
// 等待线程的数量为10 CountDownLatch c = new CountDownLatch(10);
第二步:主线程阻塞
此时,主线程调用CountDownLatch的await()方法,阻塞当前线程(即:主线程在闭锁上等待),直到计数器的值为0。
//主线程在闭锁上等待,直到计数器的值为0 countDownLatch.await()
第三步:计数器减1
主线程闭锁等待后,子线程开始执行任务,每当一个线程完成了自己的任务后,调用CountDownLatch的countDown()方法,计数器的值就会减1,如下所示:
//countDown():计数器减一,表示线程完成任务 CountDownLatch.countDown()
上面的初始线程10陆续减完,当计数器值到达0时,它表示所有的线程已经完成了任务,此时,在闭锁上等待的主线程就可以恢复执行任务。
CountDownLatch使用示例
这里举个例子,例如:在比赛跑步时有 5 个运动员参赛,终点有一个裁判员,什么时候比赛结束呢?那就是当所有人都跑到终点之后,宣布比赛结束。
示例如下:
public class CountDownLatchDemo{ public static void main(String[] args) throws InterruptedException { CountDownLatch latch = new CountDownLatch(5); ExecutorService service = Executors.newFixedThreadPool(5); for (int i = 0; i < 5; i++) { final int no = i + 1; Runnable runnable = new Runnable() { @Override public void run() { try { Thread.sleep((long) (Math.random() * 10000)); System.out.println(no + "号运动员完成了比赛。"); } catch (InterruptedException e) { e.printStackTrace(); } finally { latch.countDown(); } } }; service.submit(runnable); } System.out.println("等待5个运动员都跑完....."); latch.await(); System.out.println("所有人都跑完了,比赛结束。"); } }
在这段代码中,我们新建了一个初始值为 5 的 CountDownLatch。
主线程打印完“等待 5 个运动员都跑完”这句话后,会调用 await() 方法,代表让主线程开始等待。
每个任务代表:一个运动员,每个运动员跑完比赛,会调用 countDown 方法来把计数减 1。
执行结果如下:
主线程等待所有运动员都跑完比赛后,直到 5 个运动员都完成了比赛之后,也就是说直到计数器为0,主线程才会继续。
CountDownLatch应用场景
倒数计时器,例如:一种典型的场景就是火箭发射,在火箭发射前,为了保证万无一失,往往还要进行各项设备、仪器的检查。
只有等所有检查完毕后,引擎才能点火,这种场景就非常适合使用。
同样,应用程序的主线程,希望启动所有的框架的子线程执行完后,最后再执行主线程,这种场景也是非常适合的。
陈睿mikechen
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》