文档章节

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

阿拉德大陆的魔法师
 阿拉德大陆的魔法师
发布于 2016/11/26 11:20
字数 908
阅读 2006
收藏 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
721
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
994
1
安卓中高级开发工程师面试之——面试永远逃不掉的Java线程面试题

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

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

没有更多内容

加载失败,请刷新页面

加载更多

Mybatis Plus删除

/** @author beth @data 2019-10-17 00:30 */ @RunWith(SpringRunner.class) @SpringBootTest public class DeleteTest { @Autowired private UserInfoMapper userInfoMapper; /** 根据id删除......

一个yuanbeth
今天
4
0
总结

一、设计模式 简单工厂:一个简单而且比较杂的工厂,可以创建任何对象给你 复杂工厂:先创建一种基础类型的工厂接口,然后各自集成实现这个接口,但是每个工厂都是这个基础类的扩展分类,spr...

BobwithB
今天
5
0
java内存模型

前言 Java作为一种面向对象的,跨平台语言,其对象、内存等一直是比较难的知识点。而且很多概念的名称看起来又那么相似,很多人会傻傻分不清楚。比如本文我们要讨论的JVM内存结构、Java内存模...

ls_cherish
今天
4
0
友元函数强制转换

友元函数强制转换 p522

天王盖地虎626
昨天
5
0
js中实现页面跳转(返回前一页、后一页)

本文转载于:专业的前端网站➸js中实现页面跳转(返回前一页、后一页) 一:JS 重载页面,本地刷新,返回上一页 复制代码代码如下: <a href="javascript:history.go(-1)">返回上一页</a> <a h...

前端老手
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部