Java多线程-CountDownLatch、CyclicBarrier、Semaphore
上次简单了解了多线程中锁的类型,今天要简单了解下多线程并发控制的一些工具类了。
1. 概念说明:
CountDownLatch:相当于一个待执行线程计数器,当计数减为零时表示所有待执行线程都已执行完毕,等待被计数线程结果的(即使用await()的)线程可以继续执行(await()后面的代码)了。
CyclicBarrier:可循环屏障,相当于一个准备执行线程计数器,当计数减为零时表示所有待执行线程(这些线程需要同时开始工作)都已做好准备工作,可以开始工作了。
Semaphore:允许并发线程数,semaphore.acquire()和semaphore.release()方法总是成对出现,而这对方法之间的代码最多允许多少个线程访问是由Semaphore semaphore=new Semaphore(n)的n决定的。
2. 构造实际场景,使用示例
设想一个赛跑场景,一共有10个运动员参赛,所有运动员必须同时起跑(CyclicBarrier控制),而计分结束必须在所有运动员都跑完全程之后(CountDownLatch控制),但是学校操场只有4条跑道(Semaphore),那么就要让运动员分三批进行比赛,每次最多4人入场:
import com.alibaba.fastjson.JSONObject; import org.apache.commons.lang3.concurrent.BasicThreadFactory; import org.junit.Test; import java.util.concurrent.*; public class MultiThreadsTest { private volatile ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>(); // 声明一个线程池,用于线程管理 ThreadPoolExecutor executor = new ThreadPoolExecutor(4, 4, 20, TimeUnit.MICROSECONDS, new LinkedBlockingQueue<>(), new BasicThreadFactory.Builder().namingPattern("Runner-%d").build(), new ThreadPoolExecutor.CallerRunsPolicy()); @Test public void testMultiControl() { // 跑道数 int runways = 4; // 参赛总人数 int runners = 10; // 参赛人数多于跑道数,需分批比赛 int batch = 1; // 当运动员总数多于跑道数,最多runways人入场 while (runners >= runways) { runningGame(batch++, runways); runners = runners - runways; } // 最后一批,还剩几个人,就几个人入场 runningGame(batch, runners); System.out.println("\n所有选手都已跑完,现在宣布比赛结果:\n" + JSONObject.toJSONString(map)); } private void runningGame(int batch, int runners) { System.out.println("第" + batch + "批,共" + runners + "人,运动员正在进场..."); // 每批允许runways个运动员入场 Semaphore semaphore = new Semaphore(runners); // 每批runways个运动员必须都准备好,同时起跑 CyclicBarrier barrier = new CyclicBarrier(runners); // 每批runways个运动员都跑完全程,裁判这一批计分结束 CountDownLatch latch = new CountDownLatch(runners); for (int i = runners; i > 0; i--) { // 每个运动员都是一个独立奔跑的线程 executor.execute(() -> { try { // 每个运动员进场都会占用一个跑道 semaphore.acquire(); // 每个运动员就位都会通知barrier,等所有跑道上的运动员都就位,大家就一起跑! barrier.await(); running(Thread.currentThread().getName()); // 每个运动员跑完都要让出自己的跑道(为下一批运动员让路) semaphore.release(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } finally { // 每个运动员跑完都要通知裁判为自己计分 latch.countDown(); } }); } try { // 跑道上所有运动员都跑完,则裁判计分结束 latch.await(); System.out.println("第" + batch + "批,共" + runners + "人,计分结束"); } catch (InterruptedException e) { System.out.println(e.getStackTrace()); } } private void running(String name) { long start = System.currentTimeMillis(); System.out.println(name + " running started ..."); System.out.println(name + ": I'm running.\taudience: Yes, I see.\t" + name + ":I'm done running.\taudience: Well done!"); try { // 跑太快,歇会儿 TimeUnit.MILLISECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(name + " running completed"); // 裁判将所有运动员的分数都记录在map中 map.put(name, (System.currentTimeMillis() - start) + "ms"); } }
运行结果
3. 代码运行结果分析:
乍看上面代码和运行结果好像都没什么问题,每批允许4人进场,总是同时开始跑,也都等到每批选手都跑完后该批计分结束,countDownLatch和CyclicBarrier确实都起到了各自的作用,但是Semaphore呢?好像也确实是限制了只允许4个线程同时访问这段代码,然而在你一次只有4个选手的情况下,它当然是最多4个线程访问了,其实Semaphore的工作已经由方法入参给限定了啊,Semaphore的作用何在呢?那么假如学校原本有4个跑道,但是比赛开始之后却发现有一个入场通道坏了,变成了每次只能有3个人入场,但是场内的裁判并不知道,还在等待着按每4人一批进行比赛,那将会是什么结果呢?
我们修改代码看下:其他部分不变,只把允许入场的运动员数减1,然后再运行Test发现程序一直处于“第一批运动员进场”过程中,说明Semaphore这个变量已经起到了它的作用,就是每次只允许3个运动员进场,而且放入3个运动员后就会进行等待,等待这3个运动员比赛结束再放下一批进场,而场内的裁判并不知道可入场人数已经变化,还在等待着第4名选手入场才吹响开跑号声,因此入场管理员Semaphore和起跑裁判官CyclicBarrier就会陷入无法终止的相互等待,程序一直无法打破这种等待循环,因而进入停滞状态,这就是一种简单的死锁场景了。
4. 总结
这里只是简单说明这三个工具有用法,场景并不十分合理,其实这三者通常独立使用,一般不会碰到三者同时上场的机会。
Java多线程-CountDownLatch、CyclicBarrier、Semaphore的更多相关文章
- Java并发编程工具类 CountDownLatch CyclicBarrier Semaphore使用Demo
Java并发编程工具类 CountDownLatch CyclicBarrier Semaphore使用Demo CountDownLatch countDownLatch这个类使一个线程等待其他线程 ...
- 并发包下常见的同步工具类详解(CountDownLatch,CyclicBarrier,Semaphore)
目录 1. 前言 2. 闭锁CountDownLatch 2.1 CountDownLatch功能简介 2.2 使用CountDownLatch 2.3 CountDownLatch原理浅析 3.循环 ...
- CountDownLatch/CyclicBarrier/Semaphore 使用过吗?
CountDownLatch/CyclicBarrier/Semaphore 使用过吗?下面详细介绍用法: 一,(等待多线程完成的)CountDownLatch 背景; countDownLatch ...
- 并发包下常见的同步工具类(CountDownLatch,CyclicBarrier,Semaphore)
在实际开发中,碰上CPU密集且执行时间非常耗时的任务,通常我们会选择将该任务进行分割,以多线程方式同时执行若干个子任务,等这些子任务都执行完后再将所得的结果进行合并.这正是著名的map-reduce思 ...
- 转:java多线程CountDownLatch及线程池ThreadPoolExecutor/ExecutorService使用示例
java多线程CountDownLatch及线程池ThreadPoolExecutor/ExecutorService使用示例 1.CountDownLatch:一个同步工具类,它允许一个或多个线程一 ...
- Java中的4个并发工具类 CountDownLatch CyclicBarrier Semaphore Exchanger
在 java.util.concurrent 包中提供了 4 个有用的并发工具类 CountDownLatch 允许一个或多个线程等待其他线程完成操作,课题点 Thread 类的 join() 方法 ...
- 多线程中 CountDownLatch CyclicBarrier Semaphore的使用
CountDownLatch 调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行.也可以传入时间,表示时间到之后,count还没有为0的时候,就会继续执行. package ...
- 等待某(N)个线程执行完再执行某个线程的几种方法(Thread.join(),CountDownLatch,CyclicBarrier,Semaphore)
1.main线程中先调用threadA.join() ,再调用threadB.join()实现A->B->main线程的执行顺序 调用threadA.join()时,main线程会挂起,等 ...
- CountDownLatch/CyclicBarrier/Semaphore 使用过吗
CountDownLatch 让一些线程堵塞直到另一个线程完成一系列操作后才被唤醒.CountDownLatch 主要有两个方法,当一个或多个线程调用 await 方法时,调用线程会被堵塞,其他线程调 ...
- java 多线程 day15 CyclicBarrier 路障
import java.util.concurrent.CyclicBarrier;import java.util.concurrent.ExecutorService;import java.ut ...
随机推荐
- SQL SERVER数据库日常使用总结
以下内容为平时工作自己个人总结,仅供参考,欢迎交流 SELECT A.CBM,A.CMC,SUM(B.MJE)MJE FROM YXHIS..TBZDZTHZ A,YXHIS..TBZDZTMX B ...
- yum安装出现No package vim available解决办法
[root@iZwz96wgquf8g6okusxr0uZ yum.repos.d]# yum install yum-downloadLoaded plugins: fastestmirrorLoa ...
- 基于KVM的SRIOV直通配置及性能测试
SRIOV介绍.VF直通配置,以及包转发率性能测试 小慢哥的原创文章,欢迎转载 目录 ▪ 1. SRIOV介绍 ▪ 2. 环境说明 ▪ 3. 开启SRIOV ▪ 4. 生成VF ▪ 5. VF直通 ▪ ...
- win2008加入域控之尝试解析加入域中域控制器的dns名称失败解决办法
记录下今天遇到以前没遇到的问题 加入域的时候提示“尝试解析加入域中控制器的DNS”名称失败 可能的原因: 如果确认dns没问题 dc正常访问,那可能就是因为域控制器无法向dns注册srv记录. SRV ...
- 剑指Offer(十九)——顺时针打印矩阵
题目描述 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字. 例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 ...
- Python 爬取豆瓣TOP250实战
学习爬虫之路,必经的一个小项目就是爬取豆瓣的TOP250了,首先我们进入TOP250的界面看看. 可以看到每部电影都有比较全面的简介.其中包括电影名.导演.评分等. 接下来,我们就爬取这些数据,并将这 ...
- django报错问题解决
注意以下修改文件均是修改虚拟python环境中的文件 1.执行(venv) E:\myproj\autotest>python manage.py makemigrations报错: 解决办法: ...
- PowerShell攻击:nishang
nishanhg 下载地址:https://github.com/samratashok/nishing 1.简介 nishang的使用是要在PowerShell 3.0以上的环境中才可以正常使用 ...
- 使用JRebel插件实现SpringBoot应用代码热加载
前言 在实际的开发过程中,我们经常修改代码之后,手动的重启项目,查看修改效果.那么有没有一种方式能够快速的.自动的帮我们将修改代码自动更新,避免手动重启,从而提高开发效率呢?是有的,在我之前的文章里面 ...
- 巨杉Tech | SequoiaDB数据域及存储规划
1 背景近年来,企业的各项业务发展迅猛,客户数目不断增加,后台服务系统压力也越来越大,系统的各项硬件资源也变得非常紧张.因此,在技术风险可控的基础上,希望引入大数据技术,利用大数据技术优化现有IT系统 ...