文档章节

Java并发编程中级篇(三):使用CountDownLatch控制多线程并发等待

阿拉德大陆的魔法师
 阿拉德大陆的魔法师
发布于 2016/11/26 11:20
字数 908
阅读 2031
收藏 1

你是否遇到这这样一种情况,我们要举行一个视频会议,有若干的参会人员,需要等待所有的人员到齐后视频会议才能开始。

为了解决这个问题,Java API提供了一个线程同步辅助类CountDownLatch,使用这个辅助类可以让线程等待其它线程完成一组操作后才能执行,否则就一直等待。这个类使用一个整形参数来初始化,这个整形参数代表着等待其他线程的数量,使用await()方法让线程开始等待其他线程执行完毕,每一个线程执行完毕后后调用countDown()方法,这个方法会让CountDownLatch内部的计数器减1,当计数器变为0的时候,CountDownLatch类将唤醒所有调用await()方法并进入WAITING状态线程。

下面我们来完成这个视频会议的例子:

创建视频会议线程类VideoConference,并声明一个CountDownLatch属性controller来控制视频会议线程等待所有参会者到齐。会议线程启动后会调用await()方法并进入等待状态,每一个参会者到达后代用arrive()方法,并把controller中的计数器减1,当计数器等于0的时候会议线程继续执行。

public class VideoConference implements Runnable{
    private final CountDownLatch controller;

    public VideoConference(int number) {
        controller = new CountDownLatch(number);
    }

    public void arrive(String name) {
        System.out.printf("%s has arrived.\n", name);
        controller.countDown();
        System.out.printf("VideoConference: Waiting for %d participants.\n", controller.getCount());
    }

    @Override
    public void run() {
        System.out.printf("VidwoConference: Initialization: %d participants.\n", controller.getCount());

        try {
            controller.await();
            System.out.printf("VidwoConference: All the participants have come.\n");
            System.out.printf("VidwoConference: Let's start...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

创建参会者线程类Participant,这个类持有会议类的引用,启动后用一个随机休眠时间来模拟与会者到达所需的时间,休眠结束后代用会议类的arrive(name)方法告诉会议类,与会者到达并把CountDownLatch计数器减1。

public class Participant implements Runnable{
    private String name;
    private VideoConference videoConference;

    public Participant(String name, VideoConference videoConference) {
        this.name = name;
        this.videoConference = videoConference;
    }

    @Override
    public void run() {
        long duration = (long) (Math.random() * 10);
        try {
            TimeUnit.SECONDS.sleep(duration);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        videoConference.arrive(name);
    }
}

实现主方法类,这里我们创建并移动一个视频会议,规定参会者有10个人。然后我们启动10个参会者线程,当所有参会者都到达后,视频会议开始执行。

public class Main {
    public static void main(String[] args) {
        VideoConference videoConference = new VideoConference(10);
        Thread threadConference = new Thread(videoConference);
        threadConference.start();

        Thread[] threads = new Thread[10];
        for (int i = 0; i < 10; i++) {
            threads[i] = new Thread(new Participant("P-" + i, videoConference));
        }

        for (int i = 0; i < 10; i++) {
            threads[i].start();
        }
    }
}

查看控制台日志,我们看到每次有一个参会者到达都可以调用getCount()方法来获取计数器的值。

VidwoConference: Initialization: 10 participants.
P-0 has arrived.
VideoConference: Waiting for 9 participants.
P-4 has arrived.
VideoConference: Waiting for 8 participants.
P-2 has arrived.
VideoConference: Waiting for 7 participants.
P-5 has arrived.
VideoConference: Waiting for 6 participants.
P-8 has arrived.
VideoConference: Waiting for 5 participants.
P-3 has arrived.
VideoConference: Waiting for 4 participants.
P-6 has arrived.
VideoConference: Waiting for 3 participants.
P-1 has arrived.
VideoConference: Waiting for 2 participants.
P-7 has arrived.
VideoConference: Waiting for 1 participants.
P-9 has arrived.
VideoConference: Waiting for 0 participants.
VidwoConference: All the participants have come.
VidwoConference: Let's start...

注意,CountDownLatch并不是用来保护共享资源同步访问的,而是用来控制并发线程等待的。并且CountDownLatch只允许进入一次,一旦内部计数器等于0,再调用这个方法将不起作用,如果还有第二次并发等待,你还得创建一个新的CountDownLatch。

© 著作权归作者所有

阿拉德大陆的魔法师
粉丝 27
博文 91
码字总数 83019
作品 0
西城
程序员
私信 提问
读书笔记之《Java并发编程的艺术》-并发编程容器和框架(重要)

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
723
1
java多线程系列:通过对战游戏学习CyclicBarrier

CyclicBarrier是java.util.concurrent包下面的一个工具类,字面意思是可循环使用(Cyclic)的屏障(Barrier),通过它可以实现让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一...

huangzd
2018/01/06
0
0
读书笔记之《Java并发编程的艺术》-并发编程基础

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
4K
8
Java线程面试题 Top 50

不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题。Java语言一个重要的特点就是内置了对并发的支持,让Java大受企业和程序员的欢迎。大多数待遇丰厚的Java开发职位都要求开发者...

loda0128
2015/05/29
998
1
安卓中高级开发工程师面试之——面试永远逃不掉的Java线程面试题

不管你是Java工程师还是安卓开发工程师,只要你是计算机开发工程师,你一定在面试中遇到过有关线程的问题。Java语言一个重要的特点就是内置了对并发的支持,让Java大受企业和程序员的欢迎。大...

小饼干的梦
2018/10/12
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Phpstorm2018 永久激活

1、安装phpstorm,安装包请自行官网下载 http://www.jetbrains.com/phpstorm/download/ 2、下载JetbrainsCrack.jar文件,存放至你的phpstorm执行文件同级目录下 下载JetbrainsCrack.jar 提取...

happyfish319
6分钟前
2
0
谈一谈Android进程间通信的几种方式

###来看一下Android中除了AIDL还有哪些进程间通信的方式: 1、Bundle Bundle实现了Parcelable,所以在Android中我们可以通过Intent在不同进程间传递Bundle数据。 但是在Intent 传输数据的过程...

二营长的意大利炮手
7分钟前
2
0
互联网薪资“高开低走”,你的能力是否真的可以匹配高薪?

对于国内外主流互联网大厂,技术出身似乎已经成为各大掌门人的必备标签。谷歌 CEO 桑达尔·皮查伊、马克·扎克伯格、李彦宏、马化腾、雷军等等皆为技术人出身,都曾参与了公司内部重要产品的...

Java技术剑
8分钟前
2
0
java 多线程

线程声明周期 线程的五个状态:新建,就绪,运行,阻塞,死亡。 其中就绪和运行两个状态客户互相转换,但运行到阻塞,阻塞到就绪,只能单向转换。 刚new出的线程就是【新建】状态,调用start...

雷开你的门
10分钟前
4
0
构造器Constructor是否可被overrid

构造器不能被重写,不能用static修饰构造器,只能用public private protected这三个权限修饰符,且不能有返回语句。

无名氏的程序员
14分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部