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线程的代码:

原文发布于微信公众号 - ImportSource(importsource)

原文发表时间:2016-06-01

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏微信公众号:Java团长

Java中的多线程你只要看这一篇就够了

如果对什么是线程、什么是进程仍存有疑惑,请先Google之,因为这两个概念不在本文的范围之内。

8210
来自专栏我是攻城师

理解Java并发工具包线程池的设计

创建线程的流程依赖底层的操作系统,不同的操作系统可能不一样,此外更多的线程意味着 OS调度需要做更多的工作来决定哪一个线程可以访问资源,并且要通过OS调度切换维...

16120
来自专栏顶级程序员

40个多线程问题总结

源 / 架构师小秘圈 文 / 五月的仓颉 1、多线程有什么用? 一个可能在很多人看来很扯淡的一个问题:我会用多线程就好了,还管它有什么用?在我看来,这个回...

43070
来自专栏Linyb极客之路

并发编程之线程池

一、关于ThreadPoolExecutor 为了更好地控制多线程,JDK提供了一套Executor框架,帮助开发人员有效的进行线程控制,其本质就是一个线程池。...

46780
来自专栏芋道源码1024

【死磕Java并发】—- J.U.C之并发工具类:CyclicBarrier

此篇博客所有源码均来自JDK 1.8 CyclicBarrier,一个同步辅助类,在API中是这么介绍的: 它允许一组线程互相等待,直到到达某个公共屏障点 (c...

34940
来自专栏Linyb极客之路

邂逅多线程

用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现。说这个话其实只有一半对,因为反应“多角色”的程序代码,最起码每个角...

35680
来自专栏java技术学习之道

java线程-看这一篇就够了

15430
来自专栏JavaEdge

JUC源码分析之CyclicBarrier简介关键方法与参数源码解析CountDownLatch和CyclicBarrier的区别与联系应用场景小结

36280
来自专栏Golang语言社区

锁的优化和注意事项151

1. 锁优化的思路和方法 在[高并发Java 一] 前言中有提到并发的级别。 一旦用到锁,就说明这是阻塞式的,所以在并发度上一般来说都会比无锁的情况低一点。 这...

422110
来自专栏一枝花算不算浪漫

由初始化线程池引发的NoClassDefFoundError 异常分析

今天说的异常是一个很不常见的异常,至少我不经常见到这个异常。 首先先看下NoClassDefFoundError官方定义 : Java Virtual Ma...

11820

扫码关注云+社区

领取腾讯云代金券