文章目录

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

  1. LeetCode 1115. Print FooBar Alternately--多线程并发问题--Java解法--CyclicBarrier, synchronized, Semaphore 信号量

    此文首发于我的个人博客:zhang0peter的个人博客 LeetCode题解专栏:LeetCode题解 LeetCode 所有题目总结:LeetCode 所有题目总结 题目地址:Print FooB ...

  2. java并发学习03---CountDownLatch 和 CyclicBarrier

    CountDownLatch,顾名思义就是一个倒计时器.(其实Latch的意思是门闩,这个词的本意是不断的计数减一,减到0了就打开门闩放行,但通常我们还是叫它倒计时器) 这个倒计时器和我们传统意义上的 ...

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

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

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

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

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

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

  6. java并发编程工具类辅助类:CountDownLatch、CyclicBarrier和 Semaphore

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

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

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

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

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

  9. Jdk并发线程处理CountDownLatch、CyclicBarrier、Semaphore

    文章目录 1. CountDownLatch 1.1 描述 1.2 业务场景 1.3 代码 2. CyclicBarrier 2.1 说明 2.2 应用 2.3 代码 3. Semaphore 3.1 ...

最新文章

  1. matlab练习程序(简单图像融合)
  2. 用Windows live Writer 2012发布51cto博客
  3. gitlab project项目迁移
  4. 【Redis】CentOS7下redis的安装+supervisor管理+允许远程访问+测试部署效果
  5. 16 代码分割之错误边界与Suspense和命名导出
  6. 助力中小企业级连云端,促进工业互联网平台蓬勃发展,全套解决方案。附:技术产品
  7. mockito入门_Mockito入门
  8. 天然气压缩因子计算软件_测量天然气用什么流量计?
  9. 生成不同尺寸dimen的xml文件以及文件夹
  10. MyISAM存储引擎简介
  11. 使用hiredis接口(Synchronous API)编写redis客户端
  12. 基于Struts开发网上商城购物系统
  13. LAMMPS分子动力学模拟技术与应用 第一性原理计算方法及应用
  14. windows使用密钥登录linux服务器
  15. 单行子查询返回多个行
  16. PDF文档如何在线进行解密操作
  17. C中Ascii码对照
  18. 三种登录形式的实现—永久登录、每次进入页面登录、设置登录有效期
  19. CentOS7开启自定义热点HotSpot
  20. Ethercat 从站开发总结四:从站硬件分析

热门文章

  1. Ubuntu 20.04 在线升级node.js版本
  2. Android屏幕适配很难嘛其实也就那么回事,app架构师实践指南pdf
  3. devstack mysql_使用devstack 安装openstack
  4. 使用fragment实现tab
  5. 乐观锁原理的理解(面试加分项)
  6. Display Tag Lib
  7. 《汉明码(海明码)》通俗易懂
  8. simulink 汉明码 用法_汉明码编译码
  9. 在线解密word文档
  10. java 构造方法的理解及作用