Semaphore、CountDownLatch和CyclicBarrier
Semaphore
信号量,我们应该都在操作系统课程里学过,它是解决进程间通信和同步的常用工具,也是一种常见的模型。信号量是一个确定的二元组(s, q), s是正整型变量,q是初始状态为空的队列,s代表并发状态,操作系统利用信号量的状态s管理并发进程。如果s<=0,进程阻塞,如果s>0,进程继续执行。为了实现对s值的修改,操作系统提供了P、V操作原语,P的操作包括:s值减1,若s<=0,则进程阻塞,并将该进程插入到等待队列q中,V操作:s值加1,若s<=0,从等待队列中移出一个进程,解除其阻塞状态。
Java提供了经典信号量(Semaphore)的实现,它通常用于控制线程数来达到限制共享资源访问的目的。
下面用信号量实现生产者消费者模型来演示下用法:
public class SemaphoreDemo {private static volatile int count = 0 ;private static final Semaphore full = new Semaphore(5);private static final Semaphore empty = new Semaphore(0);private static final Semaphore mutex = new Semaphore(1);public static void main(String[] args) {ExecutorService threadPool = Executors.newFixedThreadPool(10);threadPool.execute(() -> {while(true){try {full.acquire();mutex.acquire();count++;System.out.println("生产了1个资源, 目前还有" + count + "个资源");Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();} finally {mutex.release();empty.release();}}});threadPool.execute(() -> {while(true){try {empty.acquire();mutex.acquire();count--;System.out.println("消费了1个资源, 目前还有" + count + "个资源");Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();} finally {mutex.release();full.release();}}});}
}
full信号量限制了最多生产的资源数量,empty信号量限制了资源为空无法消费,mutex信号量相当于互斥锁,避免count读写不一致。总的来说,可以看出Semaphore就是个计数器,其基本逻辑基于acquire/release,acquire获取资源若获取不到则阻塞,release释放资源并唤醒阻塞的线程,信号量构造方法中还有个公平的参数这里没有演示。
CountDownLatch
作用是允许一个或多个线程等待直到其他线程中的某个操作完成。使用给定数值初始化CountDownLatch,调用countDown方法会减少计数器的值,调用await方法会阻塞直到当前计数达到零,之后释放所有等待的线程,但是注意计数器到0的时候不会自动重置(这也是和CyclicBarrier的区别之一)。
如果现在有这样一个场景,一批人叫了很多出租车,但是一车只能坐5个人,坐完后等下一辆车继续,用CountDownLatch如何实现?
代码如下:
public class CountDownLatchDemo {public static void main(String[] args) throws InterruptedException {CountDownLatch latch = new CountDownLatch(6);ExecutorService executor = Executors.newFixedThreadPool(10);for(int i = 0; i < 5; i++){executor.execute(() -> {System.out.println("First batch has executed!");latch.countDown();});}for(int i = 0; i < 5; i++){executor.execute(() -> {try {latch.await();System.out.println("Second batch has executed!");} catch (InterruptedException e) {e.printStackTrace();}});}while(latch.getCount() != 1){Thread.sleep(1000);}latch.countDown();System.out.println("Wait for first batch finish!");}
}
执行结果如下:
第一批执行完后,由于第二批代码中调用了await方法所以阻塞,直到coutdownlatch的计数器减到0为止。
CyclicBarrier
一种同步辅助工具,允许一组线程全部等待到达某个屏障。用这个工具类实现上述场景:
public class CyclicBarrierDemo {public static void main(String[] args) {//final CyclicBarrier cyclicBarrier = new CyclicBarrier(5, () -> new Thread(() -> System.out.println("Wait for batch finish!")).start());final CyclicBarrier cyclicBarrier = new CyclicBarrier(5, () -> System.out.println("Wait for batch finish!"));for(int i = 0; i < 10; i++){new Thread(() -> {try {System.out.println("The batch has executed!");cyclicBarrier.await();} catch (InterruptedException | BrokenBarrierException e) {e.printStackTrace();}}).start();}}
}
执行结果如下:
CyclicBarrier支持一个回调函数,每当一轮线程结束后,下一轮线程开始前,这个回调函数都会被调用一次,而且这个回调函数是执行在一个回合里最后执行await()的线程上。
注意上述代码中注释了一行,注释的写法意味着新开一个线程执行回调函数,那么回调函数会异步执行。
CountDownLatch和CyclicBarrier的区别:
CountDownLatch是不可以重置的,所以无法重用;而CyclicBarrier则没有这种限制,可以重用。 CountDownLatch的基本操作组合是countDown/await。调用await的线程等待countDown直到足够的次数,不管是在一个线程还是多个线程里countDown。
CyclicBarrier的基本操作是await,当所有的线程都调用了await,才会继续进行任务,并自动进行重置。注意,正常情况下,CyclicBarrier的重置都是自动发生的,如果我们调用reset方法,但还有线程在等待,就会导致等待线程被打扰,抛出BrokenBarrierException异常。
转载于:https://www.cnblogs.com/morph/p/11165938.html
Semaphore、CountDownLatch和CyclicBarrier相关推荐
- Java并发编程之CountDownLatch、CyclicBarrier和Semaphore
前言 本文为对CountDownLatch.CyclicBarrier.Semaphore的整理使用 CountDownLatch CountDownLatch类位于java.util.concurr ...
- 使用Java辅助类(CountDownLatch、CyclicBarrier、Semaphore)并发编程
在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch,CyclicBarrier和Semaphore,今天我们就来学习一下这三个辅助类的用法 一.C ...
- Java并发编程:CountDownLatch、CyclicBarrier和 Semaphore
2019独角兽企业重金招聘Python工程师标准>>> 在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch,CyclicBarr ...
- 并发工具类:CountDownLatch、CyclicBarrier、Semaphore
在多线程的场景下,有些并发流程需要人为来控制,在JDK的并发包里提供了几个并发工具类:CountDownLatch.CyclicBarrier.Semaphore. 一.CountDownLatch ...
- CountDownLatch、CyclicBarrier、Semaphore的区别,你知道吗?
点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:是时候扔掉Postman了,又一个被低估的IDEA插件出来了...个人原创+1博客:点击前往,查看更多 链接:h ...
- JAVA所有选手就位后比赛开始_Java多线程-CountDownLatch、CyclicBarrier、Semaphore
上次简单了解了多线程中锁的类型,今天要简单了解下多线程并发控制的一些工具类了. 1. 概念说明: CountDownLatch:相当于一个待执行线程计数器,当计数减为零时表示所有待执行线程都已执行完毕 ...
- Java并发编程:CountDownLatch、CyclicBarrier和Semaphore
2019独角兽企业重金招聘Python工程师标准>>> Java并发编程:CountDownLatch.CyclicBarrier和Semaphore 在java 1.5中,提供了一 ...
- JUC多线程:CountDownLatch、CyclicBarrier、Semaphore同步器原理总结
一.CountDownLatch: 1.什么是 CountDownLatch: CountDownLatch,闭锁,就是一个基于 AQS 共享模式的同步计数器,它内部的方法都是围绕 AQS 实现的.主 ...
- Java多线程(八)之Semaphore、CountDownLatch、CyclicBarrier、Exchanger
一.引言 Semaphore :一个计数信号量 CountDownLatch :一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线 ...
最新文章
- C++下简单的socket编程
- 让delphi程序不受WINDOWS日期格式的影响
- Adobe的学者约翰—沃洛克博士
- 转换mp3名称的小程序
- 解决读写分离过期读的几个方案
- 【移植驱动到Linux3.4.2内核之二】LCD,触摸屏,按键,USB等驱动程序的移植心得总结
- SpringMvc 03 非注解形式下的映射器与适配器
- c语言i o编程,【linux】基本I/O操作标准I/O操作(c语言编程)
- echart 世界地图发光_echarts生成世界地图,百度echarts生成世界地图方法
- 电脑字体变成繁体中文怎么更改过来呢
- 美食短视频怎么拍才会吸引人?美食+定位,助你吸粉引流
- python爬取淘宝商品评论_Python爬取淘宝评论!听说差评才是最真实的?
- printJs 打印HTML 去掉页眉页脚
- 『毒舌电影社区』干掉烂片,让烂片无路可走!
- 弘辽科技跨境电商创业不得不知的6个问题,第一,哪些人适合,有哪些门槛
- 计算机会计和传统手工会计的区别,电算化会计与传统手工会计的区别
- 这些片子你猜到结局了吗?
- Unity3D-Shader之两张图片叠加并且通过颜色调控
- 电脑文件定时备份到U盘
- ANSYS APDL学习(9):命令流报错No *Do trips needed, enter *ENDDO .解决办法
热门文章
- Java Web 前端高性能优化(一)
- 优先队列 HDOJ 5437 Alisha's Party
- SQL Server查询死锁并KILL
- linux 下简单的ftp客户端程序
- idea提示 cannot resolve symbol “println
- hadoop的HA高可用配置(没有搞完)
- neo4jd3的使用流程(转载)
- MySQL my.cnf file - Found option without preceding group
- Finding Structure in Time论文解读
- Python修饰器的函数式编程