这三者都是java并发包的工具类,提供了比synchronized更加高级的各种同步结构,可以实现更加丰富的多线程操作。

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相关推荐

  1. Java并发编程之CountDownLatch、CyclicBarrier和Semaphore

    前言 本文为对CountDownLatch.CyclicBarrier.Semaphore的整理使用 CountDownLatch CountDownLatch类位于java.util.concurr ...

  2. 使用Java辅助类(CountDownLatch、CyclicBarrier、Semaphore)并发编程

    在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch,CyclicBarrier和Semaphore,今天我们就来学习一下这三个辅助类的用法 一.C ...

  3. Java并发编程:CountDownLatch、CyclicBarrier和 Semaphore

    2019独角兽企业重金招聘Python工程师标准>>> 在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch,CyclicBarr ...

  4. 并发工具类:CountDownLatch、CyclicBarrier、Semaphore

    在多线程的场景下,有些并发流程需要人为来控制,在JDK的并发包里提供了几个并发工具类:CountDownLatch.CyclicBarrier.Semaphore. 一.CountDownLatch ...

  5. CountDownLatch、CyclicBarrier、Semaphore的区别,你知道吗?

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:是时候扔掉Postman了,又一个被低估的IDEA插件出来了...个人原创+1博客:点击前往,查看更多 链接:h ...

  6. JAVA所有选手就位后比赛开始_Java多线程-CountDownLatch、CyclicBarrier、Semaphore

    上次简单了解了多线程中锁的类型,今天要简单了解下多线程并发控制的一些工具类了. 1. 概念说明: CountDownLatch:相当于一个待执行线程计数器,当计数减为零时表示所有待执行线程都已执行完毕 ...

  7. Java并发编程:CountDownLatch、CyclicBarrier和Semaphore

    2019独角兽企业重金招聘Python工程师标准>>> Java并发编程:CountDownLatch.CyclicBarrier和Semaphore 在java 1.5中,提供了一 ...

  8. JUC多线程:CountDownLatch、CyclicBarrier、Semaphore同步器原理总结

    一.CountDownLatch: 1.什么是 CountDownLatch: CountDownLatch,闭锁,就是一个基于 AQS 共享模式的同步计数器,它内部的方法都是围绕 AQS 实现的.主 ...

  9. Java多线程(八)之Semaphore、CountDownLatch、CyclicBarrier、Exchanger

    一.引言 Semaphore               :一个计数信号量 CountDownLatch          :一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线 ...

最新文章

  1. C++下简单的socket编程
  2. 让delphi程序不受WINDOWS日期格式的影响
  3. Adobe的学者约翰—沃洛克博士
  4. 转换mp3名称的小程序
  5. 解决读写分离过期读的几个方案
  6. 【移植驱动到Linux3.4.2内核之二】LCD,触摸屏,按键,USB等驱动程序的移植心得总结
  7. SpringMvc 03 非注解形式下的映射器与适配器
  8. c语言i o编程,【linux】基本I/O操作标准I/O操作(c语言编程)
  9. echart 世界地图发光_echarts生成世界地图,百度echarts生成世界地图方法
  10. 电脑字体变成繁体中文怎么更改过来呢
  11. 美食短视频怎么拍才会吸引人?美食+定位,助你吸粉引流
  12. python爬取淘宝商品评论_Python爬取淘宝评论!听说差评才是最真实的?
  13. printJs 打印HTML 去掉页眉页脚
  14. 『毒舌电影社区』干掉烂片,让烂片无路可走!
  15. 弘辽科技跨境电商创业不得不知的6个问题,第一,哪些人适合,有哪些门槛
  16. 计算机会计和传统手工会计的区别,电算化会计与传统手工会计的区别
  17. 这些片子你猜到结局了吗?
  18. Unity3D-Shader之两张图片叠加并且通过颜色调控
  19. 电脑文件定时备份到U盘
  20. ANSYS APDL学习(9):命令流报错No *Do trips needed, enter *ENDDO .解决办法

热门文章

  1. Java Web 前端高性能优化(一)
  2. 优先队列 HDOJ 5437 Alisha's Party
  3. SQL Server查询死锁并KILL
  4. linux 下简单的ftp客户端程序
  5. idea提示 cannot resolve symbol “println
  6. hadoop的HA高可用配置(没有搞完)
  7. neo4jd3的使用流程(转载)
  8. MySQL my.cnf file - Found option without preceding group
  9. Finding Structure in Time论文解读
  10. Python修饰器的函数式编程