Java 并发编程系列: CountDownLatch (上厕所的案例)

时间:2022-05-07
本文章向大家介绍Java 并发编程系列: CountDownLatch (上厕所的案例),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

1、What is CountDownLatch?

CountDownLatch提供了一种同步机制,可以允许一个或多个线程等待,直到其他线程上的一系列操作完成后,那个等待的线程再携手和其他线程继续走下去。用一句话大白话就是:我等你们,你们上完厕所,我再和你们一块出发。像这样的需求在java 中怎么实现呢?就需要使用CountDownLatch

要想学会使用CountDownLatch,只要搞清楚下面三个点,就可以了:

1、指定一个count。比如:CountDownLatch startSignal = new CountDownLatch(1);// 开始执行信号

2、明白await()方法。当count变为0的时候就继续往下执行,没到0就一直卡着。

3、明白countDown()方法。这个方法负责递减,每次减1。

概念简单的说一说,talk is cheap,还是上代码。

2、When should we use CountDownLatch ?

Use CountDownLatch when one of Thread like main thread, require to wait for one or more thread to complete, before its start doing processing.

当我们希望在main线程里,必须等待其他子线程执行完以后继续往下执行。这个时候,我们就需要用到CountDownLatch

按照上面的需求,在你不知道CountDownLatch之前,你也许会这样写你的代码:

我们希望输出这样的结果:

然而真正的输出结果是这样的:

使用了CountDownLatch后,像下面这样:

输出结果是一个顺序的,与主线程同步的状态:

3、How CountDownLatch works ?

现在我们来一步步复盘CountDownLatch执行顺序。

1、首先我们定义了CountDownLatch doneSignal = new CountDownLatch(N);。完成信号。

2、然后我们定义了CountDownLatch startSignal = new CountDownLatch(1);。开始信号。

3、然后我们使用for循环来启动10个线程。我们分别把完成信号和开始信号传入线程。像这样:

  for (int i = 1; i <= N; i++) {    new Thread(new Worker(i,doneSignal, startSignal)).start();// 线程启动了
  }

4、线程按理说已经开始执行了。然而,我们发现在Work类中的run方法里有这样一句话:

    startSignal.await(); // 等待开始执行信号的发布

这句话导致了我们之前启动的10个线程全都处于等待状态,他们正在等待发号施令。那么这些阻塞的线程,什么时候开始运行呢? 根据前面我们说的,当count=0的时候就开始继续往下执行了。所以你也许知道下一步怎么触发他们了。 万事俱备,只欠东风!

5、给东风呗,让10个线程run起来了,没错,通过一句话就可以了:

   startSignal.countDown();// 开始执行啦

我们通过countDown()方法把count变为了0,这时候10个线程就跑起来了。 自然每个线程执行完都必须要--1啊,就是要调用完成信号的countDown()方法。

6、就这样,当10个线程运行完以后,由于每个线程执行完都会对count减1。自然10个线程执行完以后,doneSignal 的count就为0。 我们知道,当count为0时,之前一直await的main线程,也就是主线程就继续往下执行了。

main线程的代码: