文章插图
package cn.itcast.thread;import java.util.concurrent.CyclicBarrier;import java.util.concurrent.TimeUnit;public class Test17 {// 定义同步屏障对象private static CyclicBarrier cb = new CyclicBarrier(2);public static void main(String[] args) {// 创建线程1new Thread(() -> {try {System.out.println("达到屏障阻塞线程数:" + cb.getNumberWaiting());cb.await(); // 达到屏障阻塞,+1System.out.println("运行结束1"); // 不会运行} catch (Exception e) {e.printStackTrace();}}).start();// 创建线程2new Thread(() -> {try {System.out.println("达到屏障阻塞线程数:" + cb.getNumberWaiting());cb.await(); // 达到屏障阻塞,+1System.out.println("运行结束2"); // 不会运行} catch (Exception e) {e.printStackTrace();}}).start();try {TimeUnit.SECONDS.sleep(2);// 会运行,没有到达屏障,不会阻塞System.out.println("主线程完成,拦截线程数:" + cb.getParties()+ " , 达到屏障阻塞线程数:" + cb.getNumberWaiting());} catch (InterruptedException e) {e.printStackTrace();}}}
运行效果由于两个子线程的调度是由CPU决定的,两个子线程都有可能先执行,所以会产生两种输出:
文章插图
说明:由于所有线程都达到屏障,所有阻塞线程被释放,所以阻塞线程为0
如果把new CyclicBarrier(2)修改成new CyclicBarrier(3),则主线程和子线程会永远等待 , 因为没有第三个线程执行await方法,即没有第三个线程到达屏障,所以之前到达屏障的两个线程都不会继续执行 。
private static CyclicBarrier cb = new CyclicBarrier(3);
文章插图
19、并发工具类:Semaphore(信号量)目标:掌握Semaphore的使用
介绍
Semaphore(信号量)限制着访问某些资源的线程数量,在到达限制的线程数量之前,线程能够继续进行资源的访问 , 一旦访问资源的数量到达限制的线程数量 , 这个时候线程就不能够再去获取资源,只有等待有线程退出资源的获取 。
应用场景
比如模拟一个停车场停车信号,假设停车场只有两个车位 , 一开始两个车位都是空的 。这时同时来了两辆车,看门人允许它们进入停车?。?然后放下车拦 。以后来的车必须在入口等待,直到停车场中有车辆离开 。这时,如果有一辆车离开停车?。?看门人得知后,打开车拦,放入一辆,如果又离开一辆,则又可以放入一辆,如此往复 。
文章插图
API方法
信号量维护了一个许可集 。如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可 。每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者让其运行 。但是,不使用实际的许可对象,Semaphore 只对可用许可的号码进行计数,并采取相应的行动 。
所以一个Semaphore 信号量有且仅有 3 种操作,且它们全部是原子的 。
- 初始化许可集、增加许可、获取许可 。
- 增加许可,release()方法释放一个阻塞 , 增加一个许可 。
推荐阅读
- “正科级”公务员退休后有多少钱?40年工龄的话,预计是这个数
- 女人对你有好感,哪怕嘴上不说,这7个肢体语言也藏不住
- “无性婚姻”有多可怕?听听3个过来人的故事,希望你能引以为戒
- 家里放了几年的红茶、绿茶、普洱茶,还能喝吗?医生告诉你实话
- 求求你们别再换脸了,就像好好的一盘菜吃出苍蝇的感觉!
- 拒认儿子巴图20年,晚年态度翻转,是居心叵测,还是真后悔?
- 教你自己制作花生酱,教你自制花生酱
- 微博该咋得才可以删除评论,为什么微博评论删除后还有显示
- 《我知道我爱你》热播:和冬天适配的偶像剧
- 李善均离世早有端倪?留下遗书后离家,现场有点燃闪电弹的痕迹