并发学习之CountDownLatch、CyclicBarrier以及Semaphore
文章目录
- 一、java.util.concrrent.CountDownLatch
- 1.源码
- 2.基本使用:在循环中每个线程调用它的countDown()使count--,当count=0时,调用它的await()等待为所有需要的线程任务完成
- 3.目的:它不考虑中间线程的执行顺序,只考虑当count reaches zero(count=0)时,将最后一个线程调用
- Demo1 验证:不考虑同学走的顺序,班长最后锁门问题
- 问题:我们发现不能总得出班长最后锁门。
- Demo2 验证:秦灭六国,一统华夏。要求:秦国最后完成大一统
- 问题:我们使用CountDownLatch规定当六国灭亡后,秦才真正的统一,那如何将数字变换为六国名称?
- 二、java.util.concrrent.CyclicBarrier
- 1.源码:构造方法推荐使用public CyclicBarrier(int parties, Runnable barrierAction)
- 2.基本使用:通过给定的初值与线程,阻塞其他每个线程,最后参数上的线程开始执行。通过++循环并调用CyclicBarrier.await()阻塞其他线程。
- 3.目的:同样不考虑中间线程的实际执行过程,阻塞其他每个线程,最后执行参数上的线程。
- Demo 验证:CyclicBarrierDemo的使用——大秦一统
- Demo 验证:CyclicBarrierDemo的使用——七龙珠
- 三、java.util.concurrent.Semaphore
- 1.源码:推荐构造方法初始值,是否公平锁,true->公平,false->非公平
- 2.基本使用:semaphore.acquire()、Semaphore.release()
- 3.目的:用于多个线程的互斥作用、用于并发线程数的控制
- Demo 验证Semaphore:秦国大一统
- Demo 验证Semaphore:七人停车,有三个车位
一、java.util.concrrent.CountDownLatch
1.源码
2.基本使用:在循环中每个线程调用它的countDown()使count–,当count=0时,调用它的await()等待为所有需要的线程任务完成
从JDK1.5开始的用于多线程控制的CountDownLatch,提供了一个初始值为正数的参数,也就是count,
在循环中每个线程调用它的countDown()使count–,当count=0时,调用它的await()等待为所有需要的线程任务完成。
3.目的:它不考虑中间线程的执行顺序,只考虑当count reaches zero(count=0)时,将最后一个线程调用
它不考虑中间线程的执行顺序,只考虑当count reaches zero(count=0)时,将最后一个线程调用。
请看官方示例代码:
<pre> {@code* class Driver { // ...* void main() throws InterruptedException {* CountDownLatch startSignal = new CountDownLatch(1);* CountDownLatch doneSignal = new CountDownLatch(N);** for (int i = 0; i < N; ++i) // create and start threads* new Thread(new Worker(startSignal, doneSignal)).start();** doSomethingElse(); // don't let run yet* startSignal.countDown(); // let all threads proceed* doSomethingElse();* doneSignal.await(); // wait for all to finish* }* }
Demo1 验证:不考虑同学走的顺序,班长最后锁门问题
//模拟班长最后锁门问题
public class CountDownLatchDemo {public static void main(String[] args) {//模拟6位同学分别进行离开教室的操作for (int i = 1; i < 6; i++) {new Thread(()->{System.out.println(Thread.currentThread().getName()+" 同学走了");},String.valueOf(i)).start();}//最后输出班长锁门的情况System.out.println(Thread.currentThread().getName()+"=======班长锁门========");}
}
结果:
多执行几次:
问题:我们发现不能总得出班长最后锁门。
那么,我们可以使用CountDownLatch类来解决问题。
public class CountDownLatchDemo {//模拟班长最后锁门问题public static void main(String[] args) throws InterruptedException {//模拟5位同学分别进行离开教室的操作CountDownLatch countDownLatch = new CountDownLatch(5);//给定值为5,->0for (int i = 1; i <= 5; i++) {new Thread(()->{System.out.println(Thread.currentThread().getName()+" 同学走了");countDownLatch.countDown();//让每执行一次走,countDownLatch的值-1},String.valueOf(i)).start();}//最后输出班长锁门的情况countDownLatch.await();System.out.println(Thread.currentThread().getName()+"=======班长锁门========");}
}
结果如下:
多执行几次:
现在我们就可以控制班长最后锁门的顺序了。
Demo2 验证:秦灭六国,一统华夏。要求:秦国最后完成大一统
我们直接使用countDownLatch(6)来达到我们的目的。
public static void main(String[] args) throws InterruptedException {CountDownLatch countDownLatch = new CountDownLatch(6);//给定值为6,->0for (int i = 1; i <= 6; i++) {new Thread(()->{System.out.println(Thread.currentThread().getName()+" 亡了");countDownLatch.countDown();//让每执行一次走,countDownLatch的值-1},String.valueOf(i)).start();}//最后输出秦国一统的情况countDownLatch.await();System.out.println(Thread.currentThread().getName()+"=======秦扫六合,华夏一统========");
}
结果:
多执行几次:
问题:我们使用CountDownLatch规定当六国灭亡后,秦才真正的统一,那如何将数字变换为六国名称?
那么,我们可以使用枚举Enum来解决问题
public enum CountrySix {ONE(1,"齐国"),TWO(2,"楚国"),THREE(3,"魏国"),FOUR(4,"燕国"),FIVE(5,"韩国"),SIX(6,"赵国");//首先需要对应i值 1,2,3,4,5,6private Integer reCode;//其次需要i对应的name,齐楚燕韩赵魏private String reMessage;CountrySix(Integer reCode, String reMessage) {this.reCode = reCode;this.reMessage = reMessage;}public Integer getReCode() {return reCode;}public String getReMessage() {return reMessage;}public static String foreach_CountryEnum(int i){CountrySix[] myArray = CountrySix.values();for (CountrySix element : myArray) {if(i==element.getReCode()){return element.getReMessage();}}return null;}
}
public static void main(String[] args) throws InterruptedException {CountDownLatch countDownLatch = new CountDownLatch(6);//给定值为5,->0for (int i = 1; i <= 6; i++) {new Thread(()->{System.out.println(Thread.currentThread().getName()+" 亡了");countDownLatch.countDown();//让每执行一次走,countDownLatch的值-1},CountrySix.foreach_CountryEnum(i)).start();}//最后输出秦统一的情况countDownLatch.await();System.out.println(Thread.currentThread().getName()+"=======秦扫六合,华夏一统========");}
结果:
则完成要求!
二、java.util.concrrent.CyclicBarrier
1.源码:构造方法推荐使用public CyclicBarrier(int parties, Runnable barrierAction)
构造方法推荐使用
public CyclicBarrier(int parties, Runnable barrierAction) {//初始值,线程if (parties <= 0) throw new IllegalArgumentException();this.parties = parties;this.count = parties;this.barrierCommand = barrierAction;}
源码示例
* <pre> {@code* class Solver {* final int N;* final float[][] data;* final CyclicBarrier barrier;** class Worker implements Runnable {* int myRow;* Worker(int row) { myRow = row; }* public void run() {* while (!done()) {* processRow(myRow);** try {* barrier.await();* } catch (InterruptedException ex) {* return;* } catch (BrokenBarrierException ex) {* return;* }* }* }* }** public Solver(float[][] matrix) {* data = matrix;* N = matrix.length;* Runnable barrierAction = () -> mergeRows(...);* barrier = new CyclicBarrier(N, barrierAction);** List<Thread> threads = new ArrayList<>(N);* for (int i = 0; i < N; i++) {* Thread thread = new Thread(new Worker(i));* threads.add(thread);* thread.start();* }** // wait until done* for (Thread thread : threads)* thread.join();* }* }}</pre>
2.基本使用:通过给定的初值与线程,阻塞其他每个线程,最后参数上的线程开始执行。通过++循环并调用CyclicBarrier.await()阻塞其他线程。
通过给定的初值与线程,阻塞其他每个线程,最后参数上的线程开始执行。通过++循环并调用CyclicBarrier.await()阻塞其他线程。
3.目的:同样不考虑中间线程的实际执行过程,阻塞其他每个线程,最后执行参数上的线程。
同样不考虑中间线程的实际执行过程,阻塞其他每个线程,最后执行参数上的线程。
Demo 验证:CyclicBarrierDemo的使用——大秦一统
public class CountySixDemo {public static void main(String[] args) {CyclicBarrier cyclicBarrier = new CyclicBarrier(6, () -> {System.out.println("----大秦一统天下----");});for (int i = 1; i <= 6; i++) {int finalI = i;new Thread(()->{System.out.println(CountrySix.foreach_CountryEnum(finalI)+" 亡了啊~");try {cyclicBarrier.await();} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}}).start();}}
}
结果
Demo 验证:CyclicBarrierDemo的使用——七龙珠
public class CyclicBarrierDemo {public static void main(String[] args) {//相比较于CountdownLatch这个是给定初值,直到其他线程完成后,构造函数参数上线程执行CyclicBarrier barrier = new CyclicBarrier(7, () -> {System.out.println("=======召唤神龙=======");});for (int i = 1; i <= 7; i++) {int finalI = i;new Thread(()->{System.out.println("收集到第"+ finalI +"颗龙珠");try {//阻塞线程barrier.await();} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}},String.valueOf(i)).start();}}
}
执行结果:
集齐龙珠,神龙出世~哦吼,凡人有什么愿望快说出来吧!
那就许个愿?
三、java.util.concurrent.Semaphore
1.源码:推荐构造方法初始值,是否公平锁,true->公平,false->非公平
推荐构造方法:初始值,是否公平锁,true->公平,false->非公平
public Semaphore(int permits, boolean fair) {sync = fair ? new FairSync(permits) : new NonfairSync(permits);}
Semaphore部分关键方法:
//=======================================================semaphore.acquire()
//获取锁
public void acquire() throws InterruptedException {sync.acquireSharedInterruptibly(1);}
public final void acquireSharedInterruptibly(int arg)throws InterruptedException {if (Thread.interrupted())throw new InterruptedException();if (tryAcquireShared(arg) < 0)doAcquireSharedInterruptibly(arg);}private void doAcquireSharedInterruptibly(int arg)throws InterruptedException {final Node node = addWaiter(Node.SHARED);try {for (;;) {final Node p = node.predecessor();if (p == head) {int r = tryAcquireShared(arg);if (r >= 0) {setHeadAndPropagate(node, r);p.next = null; // help GCreturn;}}if (shouldParkAfterFailedAcquire(p, node) &&parkAndCheckInterrupt())throw new InterruptedException();}} catch (Throwable t) {cancelAcquire(node);throw t;}}
//=======================================================semaphore.release()
//释放锁
public void release() {sync.releaseShared(1);}
public final boolean releaseShared(int arg) {if (tryReleaseShared(arg)) {doReleaseShared();return true;}return false;}
private void doReleaseShared() {for (;;) {Node h = head;if (h != null && h != tail) {int ws = h.waitStatus;if (ws == Node.SIGNAL) {if (!h.compareAndSetWaitStatus(Node.SIGNAL, 0))continue; // loop to recheck casesunparkSuccessor(h);}else if (ws == 0 &&!h.compareAndSetWaitStatus(0, Node.PROPAGATE))continue; // loop on failed CAS}if (h == head) // loop if head changedbreak;}}
2.基本使用:semaphore.acquire()、Semaphore.release()
通过调用Semaphore.acquire()获取锁,之后通过Semaphore.release释放锁,达到共享资源分配的一种效果
相比之前的CountDownLatch、CyclicBarrier 可复用
3.目的:用于多个线程的互斥作用、用于并发线程数的控制
用于多个线程的互斥作用
用于并发线程数的控制
Demo 验证Semaphore:秦国大一统
public class CountrySixDemo {public static void main(String[] args) throws InterruptedException {Semaphore semaphore = new Semaphore(2);for (int i = 1; i <7; i++) {int finalI = i;new Thread(()->{try {semaphore.acquire();} catch (InterruptedException e) {e.printStackTrace();}System.out.println(program.countDownLatch.CountrySix.foreach_CountryEnum(finalI)+"兴盛起来~");try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(program.countDownLatch.CountrySix.foreach_CountryEnum(finalI)+"灭亡~");semaphore.release();}).start();}TimeUnit.SECONDS.sleep(7);System.out.println("--秦国大一统--");}}
结果:
Demo 验证Semaphore:七人停车,有三个车位
public static void main(String[] args) {Semaphore semaphore = new Semaphore(3);//位有3个for (int i = 1; i <= 7; i++) {//模拟七人停车,车位有三个,那么必有4个人停不到需要等待new Thread(()->{try {semaphore.acquire();System.out.println(Thread.currentThread().getName()+"\t抢到位置了");TimeUnit.SECONDS.sleep(2);System.out.println(Thread.currentThread().getName()+"\t占有两秒,离开车位");} catch (InterruptedException e) {e.printStackTrace();}finally {semaphore.release();}},String.valueOf(i)).start();}}
结果:
多执行几次:
并发学习之CountDownLatch、CyclicBarrier以及Semaphore相关推荐
- LeetCode 1115. Print FooBar Alternately--多线程并发问题--Java解法--CyclicBarrier, synchronized, Semaphore 信号量
此文首发于我的个人博客:zhang0peter的个人博客 LeetCode题解专栏:LeetCode题解 LeetCode 所有题目总结:LeetCode 所有题目总结 题目地址:Print FooB ...
- java并发学习03---CountDownLatch 和 CyclicBarrier
CountDownLatch,顾名思义就是一个倒计时器.(其实Latch的意思是门闩,这个词的本意是不断的计数减一,减到0了就打开门闩放行,但通常我们还是叫它倒计时器) 这个倒计时器和我们传统意义上的 ...
- 使用Java辅助类(CountDownLatch、CyclicBarrier、Semaphore)并发编程
在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch,CyclicBarrier和Semaphore,今天我们就来学习一下这三个辅助类的用法 一.C ...
- Java并发编程:CountDownLatch、CyclicBarrier和 Semaphore
2019独角兽企业重金招聘Python工程师标准>>> 在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch,CyclicBarr ...
- Java并发编程:CountDownLatch、CyclicBarrier和Semaphore
2019独角兽企业重金招聘Python工程师标准>>> Java并发编程:CountDownLatch.CyclicBarrier和Semaphore 在java 1.5中,提供了一 ...
- java并发编程工具类辅助类:CountDownLatch、CyclicBarrier和 Semaphore
在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch,CyclicBarrier和Semaphore,今天我们就来学习一下这三个辅助类的用法. 以下 ...
- Java并发编程之CountDownLatch、CyclicBarrier和Semaphore
前言 本文为对CountDownLatch.CyclicBarrier.Semaphore的整理使用 CountDownLatch CountDownLatch类位于java.util.concurr ...
- 并发工具类:CountDownLatch、CyclicBarrier、Semaphore
在多线程的场景下,有些并发流程需要人为来控制,在JDK的并发包里提供了几个并发工具类:CountDownLatch.CyclicBarrier.Semaphore. 一.CountDownLatch ...
- Jdk并发线程处理CountDownLatch、CyclicBarrier、Semaphore
文章目录 1. CountDownLatch 1.1 描述 1.2 业务场景 1.3 代码 2. CyclicBarrier 2.1 说明 2.2 应用 2.3 代码 3. Semaphore 3.1 ...
最新文章
- matlab练习程序(简单图像融合)
- 用Windows live Writer 2012发布51cto博客
- gitlab project项目迁移
- 【Redis】CentOS7下redis的安装+supervisor管理+允许远程访问+测试部署效果
- 16 代码分割之错误边界与Suspense和命名导出
- 助力中小企业级连云端,促进工业互联网平台蓬勃发展,全套解决方案。附:技术产品
- mockito入门_Mockito入门
- 天然气压缩因子计算软件_测量天然气用什么流量计?
- 生成不同尺寸dimen的xml文件以及文件夹
- MyISAM存储引擎简介
- 使用hiredis接口(Synchronous API)编写redis客户端
- 基于Struts开发网上商城购物系统
- LAMMPS分子动力学模拟技术与应用 第一性原理计算方法及应用
- windows使用密钥登录linux服务器
- 单行子查询返回多个行
- PDF文档如何在线进行解密操作
- C中Ascii码对照
- 三种登录形式的实现—永久登录、每次进入页面登录、设置登录有效期
- CentOS7开启自定义热点HotSpot
- Ethercat 从站开发总结四:从站硬件分析