在之前的文章中曾经为大家介绍了 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 深入浅出系列》