博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java计数器之CountDownLatch、CyclicBarrier、Semaphore
阅读量:5024 次
发布时间:2019-06-12

本文共 3803 字,大约阅读时间需要 12 分钟。

在Java里面有几种可以用于控制线程状态的方法,如CountDownLatch计数器、CyclicBarrier循环栅栏、Sempahore信号量。下面就分别演示下他们的使用方法:

CountDownLatch

CountDownLatch可以实现多线程之间的计数器,并实现阻塞功能。比如某个任务依赖于其他的两个任务,只有那两个任务执行结束后,它才能执行。

import java.util.concurrent.CountDownLatch;public class CountDownLatchTest2 {    public static void main(String[] args) {        // 创建计数器,初始化为2        final CountDownLatch latch = new CountDownLatch(2);        new Thread(() -> {            try {                System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");                Thread.sleep(3000);                System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕");                latch.countDown();// 减一            } catch (InterruptedException e) {                e.printStackTrace();            }        }).start();        new Thread(() -> {            try {                System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");                Thread.sleep(3000);                System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕");                latch.countDown();            } catch (InterruptedException e) {                e.printStackTrace();            }        }).start();        try {            System.out.println("等待2个子线程执行完毕...");            // 阻塞            latch.await();            System.out.println("2个子线程已经执行完毕");            System.out.println("继续执行主线程");        } catch (InterruptedException e) {            e.printStackTrace();        }    }}

执行的结果:

子线程Thread-0正在执行等待2个子线程执行完毕...子线程Thread-1正在执行子线程Thread-0执行完毕子线程Thread-1执行完毕2个子线程已经执行完毕继续执行主线程

o_Jietu20180402-174611.jpg

如上图所示,线程1需要另两个线程结束后,才能继续执行。那么就可以在两个县城里面执行countDown(),然后主线程调用await()进行阻塞。

CyclicBarrier 循环栅栏

它有两层含义,一个是栅栏,一个是循环。先看栅栏,意思就是想一堵墙一样,可以同时对多个线程状态进行管理。

o_Jietu20180402-174617.jpg

如图所示,几个线程必须同时执行完,才能继续:

import java.util.concurrent.BrokenBarrierException;import java.util.concurrent.CyclicBarrier;public class CyclicBarrierTest {    public static void main(String[] args) {        int N = 4;        CyclicBarrier barrier  = new CyclicBarrier(N);        for(int i=0;i

输出:

线程Thread-0正在写入数据...线程Thread-1正在写入数据...线程Thread-2正在写入数据...线程Thread-3正在写入数据...线程Thread-0写入数据完毕,等待其他线程写入完毕线程Thread-1写入数据完毕,等待其他线程写入完毕线程Thread-3写入数据完毕,等待其他线程写入完毕线程Thread-2写入数据完毕,等待其他线程写入完毕所有线程写入完毕,继续处理其他任务...所有线程写入完毕,继续处理其他任务...所有线程写入完毕,继续处理其他任务...所有线程写入完毕,继续处理其他任务...

循环的意思就是当计数减到0时,还可以继续使用,如:

import java.util.concurrent.BrokenBarrierException;import java.util.concurrent.CyclicBarrier;public class CyclicBarrierTest3 {    public static void main(String[] args) {        int N = 4;        CyclicBarrier barrier  = new CyclicBarrier(N);        for(int i=0;i

输出:

线程Thread-0正在写入数据...线程Thread-2正在写入数据...线程Thread-3正在写入数据...线程Thread-1正在写入数据...线程Thread-2写入数据完毕,等待其他线程写入完毕线程Thread-0写入数据完毕,等待其他线程写入完毕线程Thread-1写入数据完毕,等待其他线程写入完毕线程Thread-3写入数据完毕,等待其他线程写入完毕Thread-3所有线程写入完毕,继续处理其他任务...Thread-1所有线程写入完毕,继续处理其他任务...Thread-0所有线程写入完毕,继续处理其他任务...Thread-2所有线程写入完毕,继续处理其他任务...CyclicBarrier重用线程Thread-4正在写入数据...线程Thread-5正在写入数据...线程Thread-6正在写入数据...线程Thread-7正在写入数据...线程Thread-4写入数据完毕,等待其他线程写入完毕线程Thread-7写入数据完毕,等待其他线程写入完毕线程Thread-5写入数据完毕,等待其他线程写入完毕线程Thread-6写入数据完毕,等待其他线程写入完毕Thread-6所有线程写入完毕,继续处理其他任务...Thread-7所有线程写入完毕,继续处理其他任务...Thread-4所有线程写入完毕,继续处理其他任务...Thread-5所有线程写入完毕,继续处理其他任务...

Semaphore信号量

这个东西有点像连接池的感觉,某一时间只有几个线程能拿到资源,执行操作。

o_Jietu20180402-174621.jpg
比如下面车间工人在排队使用机器的例子:

import java.util.concurrent.Semaphore;public class SemaphoreTest {    public static void main(String[] args) {        int N = 8;            //工人数        Semaphore semaphore = new Semaphore(5); //机器数目        for(int i=0;i

输出:

工人0占用一个机器在生产...工人1占用一个机器在生产...工人2占用一个机器在生产...工人3占用一个机器在生产...工人4占用一个机器在生产...工人1释放出机器工人0释放出机器工人4释放出机器工人5占用一个机器在生产...工人2释放出机器工人7占用一个机器在生产...工人3释放出机器工人6占用一个机器在生产...工人5释放出机器工人6释放出机器工人7释放出机器

总结

  1. CountDownLatch 可以实现计数等待,主要用于某个线程等待其他几个线程
  2. CyclicBarrier 实现循环栅栏,主要用于多个线程同时等待其他线程
  3. Semaphore 信号量,主要强调只有某些个数量的线程能拿到资源执行

参考

转载于:https://www.cnblogs.com/xing901022/p/8696550.html

你可能感兴趣的文章
每天一个Linux命令(6):rmdir命令
查看>>
oracle连接的三个配置文件(转)
查看>>
Vim配置文件(Vimrc)
查看>>
RecyclerView 局部刷新(获取viewHolder 去刷新)
查看>>
PHP表单(get,post)提交方式
查看>>
使用vbs或者bat脚本修改IE浏览器安全级别和选项
查看>>
Silverlight入门
查看>>
Silverlight动态调用WEBSERVICE,WCF方法
查看>>
LeetCode 895. Maximum Frequency Stack
查看>>
模仿segmentfault 评论
查看>>
一个简单的日志函数C++
查看>>
Java 8 中如何优雅的处理集合
查看>>
IOS程序的启动过程
查看>>
连接Linux下 XAMPP集成环境中部署的禅道的数据库MariaDB
查看>>
Java操作Excel和Word
查看>>
Oracle 体系结构之ORACLE物理结构
查看>>
ORA-12538: TNS: no such protocol adapter
查看>>
盒子模型
查看>>
局域网协议
查看>>
[HNOI2012]永无乡 线段树合并
查看>>