在之前的文章中曾经为大家介绍了java并发编程的工具:BlockingQueue接口、ArrayBlockingQueue、DelayQueue、LinkedBlockingQueue、PriorityBlockingQueue、SynchronousQueue、BlockingDeque接口、ConcurrentHashMap,本文为系列文章第九篇。
CountDownLatch是一种线程同步辅助工具,它容许一个或多个线程期待其余线程正在执行的一组操作实现。CountDownLatch的概念在java并发编程中十分常见,面试也会常常被问到,所以肯定要好好了解把握。在这篇文章中,我将介绍以下几点
- CountDownLatch是什么?
- CountDownLatch 如何工作
- CountDownLatch 代码例子
CountDownLatch是什么?
CountDownLatch与其余并发编程工具类,如CyclicBarrier、Semaphore、ConcurrentHashMap和BlockingQueue等在java.util.concurrent包中与JDK 1.5一起被引入。CountDownLatch能让一个java线程期待其余线程实现工作,比方Application的主线程期待,直到其余负责启动框架服务的服务线程实现所有服务的启动。
CountDownLatch用线程数来初始化一个计数器,每当一个线程实现执行时,这个计数器就会递加。当计数为零时,示意所有线程都已实现执行,处于期待状态的主线程能够继续执行。
上面咱们应用伪代码的形式形容CountDownLatch 的作用
- 主线程启动,并为N个线程(假如n=3)初始化CountDownLatch(n)
- 启动n个线程
- 主线程阻塞期待
- 线程1执行实现,CountDownLatch -1 = 2,主线程持续阻塞
- 线程3执行实现,CountDownLatch -1 = 1,主线程持续阻塞
- 线程4执行实现,CountDownLatch -1 = 0,主线程复原执行
CountDownLatch 如何工作
CountDownLatch.java类外面定义了一个构造函数。count本质上是线程数,这个值只能设置一次,CountDownLatch没有提供办法来重置这个数。
CountDownLatch.public CountDownLatch(int count) {...}
应用CountDownLatch的主线程要去期待其余线程执行实现,所以这个主线程必须在启动其余线程后立刻调用 CountDownLatch.await()
办法,该办法阻塞主线程处于期待状态,直到其余线程执行结束,才会进行阻塞。
其余N个线程必须有CountDownLatch对象的援用,因为它们须要告诉CountDownLatch对象它们曾经实现工作。这个告诉是由办法CountDownLatch.countDown()
来实现的,每调用一次该办法,就会将构造函数中设置的初始计数count缩小1,所以当所有N个线程都调用了这个办法后count计数达到0,主线程就能够不受await()办法阻塞复原执行了。
所以CountDownLatch特地适宜于那些须要期待N个线程实现后再开始执行的场景。例如一个应用程序的启动类,在解决用户申请之前,要确保所有N个内部零碎都是处于运行状态的。
CountDownLatch 代码例子
假如咱们的应用程序主线程启动之前,要查看另外4个程序是否准备就绪,只有其余的4个程序准备就绪,咱们的主程序能力继续执行。就能够应用上面的代码来操作:
import java.util.concurrent.CountDownLatch;public class Tester { public static void main(String args[]) { //设置计数器 counter = 4 ,等于线程数 CountDownLatch countDownLatch = new CountDownLatch(4); Thread app1 = new Thread(new Application("App1", countDownLatch)); Thread app2 = new Thread(new Application("App2", countDownLatch)); Thread app3 = new Thread(new Application("App3", countDownLatch)); Thread app4 = new Thread(new Application("App4", countDownLatch)); // 启动多线程去查看其余四个程序的可用状态 app1.start(); app2.start(); app3.start(); app4.start(); try { //主线程调用await进行期待,期待上述四个线程失常实现 countDownLatch.await(); //上述四个线程查看的应用程序启动失常之后, 打印如下信息 System.out.println("All applications are up and running."); } catch(InterruptedException e) { System.out.println(e.getMessage()); } }}
子线程程序,每一个线程都持有countDownLatch对象,线程失常执行实现之时,应用countDownLatch.countDown()
办法将countDownLatch对象的计数器减1。
class Application implements Runnable { private String name; //应用程序名称 private CountDownLatch countDownLatch; public Application(String name, CountDownLatch countDownLatch) { this.name = name; this.countDownLatch = countDownLatch; } public void run() { try { System.out.println(name + " started. "); Thread.sleep(1000); } catch (InterruptedException e) { System.out.println(e.getMessage()); } System.out.println( name + " is Up and running."); //将countDownLatch计数器的值减1 countDownLatch.countDown(); }}
上述程序的打印输出后果是,能够联合输入后果去了解上文中讲述的CountDownLatch 工作原理:
App2 started. App3 started. App1 started. App4 started. App1 is Up and running.App3 is Up and running.App4 is Up and running.App2 is Up and running.All applications are up and running.
欢送关注我的博客,外面有很多精品合集
本文转载注明出处(必须带连贯,不能只转文字):字母哥博客 - zimug.com
感觉对您有帮忙的话,帮我点赞、分享!您的反对是我不竭的创作能源! 。另外,笔者最近一段时间输入了如下的精品内容,期待您的关注。
- 《手摸手教你学Spring Boot2.0》
- 《Spring Security-JWT-OAuth2一本通》
- 《实战前后端拆散RBAC权限管理系统》
- 《实战SpringCloud微服务从青铜到王者》
- 《VUE深入浅出系列》