阻塞与唤醒方式的区别

CountDownLatch计数方式

CountDownLatch是减计数。调用await()后线程阻塞。调用countDown()方法后计数减一,当计数为零时,调用await()的线程被唤醒。

CountDownLatch应用场景为:

一个或一组线程等待另一组线程完成操作后恢复执行

CountDownLatch例子: 模拟赛跑

开始时一组运动员线程等待begin计数器(初始值为1),当主线程调用begin.countDown()后begin减1,计数器为0,这一组运动员线程同时起跑。主线程等待end计数器(初始值为10)。一个运动员线程到达终点后,调用end.countDown(),end计数器减1。当所有运动员都到达终点后,end计数器为0,主线程恢复执行。

  1. package CountDownLatch;
  2. import java.util.concurrent.CountDownLatch;
  3. import java.util.concurrent.ExecutorService;
  4. import java.util.concurrent.Executors;
  5. public class RaceSimulation {
  6. public static void main(String args[]){
  7. //比赛开始的倒数锁
  8. CountDownLatch begin=new CountDownLatch(1);
  9. //比赛结束的倒数锁
  10. CountDownLatch end=new CountDownLatch(10);
  11. //十个选手跑步线程
  12. final ExecutorService exec = Executors.newFixedThreadPool(10);
  13. for(int index= 0;index<10;++index){
  14. final int NO=index+1;
  15. Runnable run = new Runnable(){
  16. @Override
  17. public void run() {
  18. try{
  19. //如果计数不为0,则一直等待
  20. //如果当前计数为0,此线程立即执行
  21. begin.await();
  22. Thread.sleep((long)(Math.random()*10000));
  23. System.out.println("No."+NO+" arrived");
  24. }catch(InterruptedException e){
  25. e.printStackTrace();
  26. }finally{
  27. //每个选手到达终点时,end就减1
  28. end.countDown();
  29. }
  30. }
  31. };
  32. exec.submit(run);
  33. }
  34. System.out.println("游戏开始:");
  35. //begin减1,开始游戏
  36. begin.countDown();
  37. //等待end变为0,即所有选手到达终点
  38. try {
  39. end.await();
  40. } catch (InterruptedException e) {
  41. e.printStackTrace();
  42. }
  43. System.out.println("游戏结束");
  44. exec.shutdown();
  45. }
  46. }

CyclicBarrier计数方式

CyclicBarrier是加计数。调用await()后线程阻塞计数器加1,当所有线程都到达屏障被阻塞后,这一组线程才一起恢复执行。

CyclicBarrier的应用场景

一组线程到达一个屏障(即执行CyclicBarrier.await())时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活。CyclicBarrier默认的构造方法是CyclicBarrier(int parties),其参数表示屏障拦截的线程数量,每个线程调用await方法告诉CyclicBarrier我已经到达了屏障,然后当前线程被阻塞。

CyclicBarier的例子

  1. package cyclicBarrier;
  2. import java.util.Random;
  3. import java.util.concurrent.BrokenBarrierException;
  4. import java.util.concurrent.CyclicBarrier;
  5. import java.util.concurrent.ExecutorService;
  6. import java.util.concurrent.Executors;
  7. public class CyclicBarrierDemo {
  8. public static void main(String[] args) {
  9. int N=4;
  10. CyclicBarrier cyclicBarrier=new CyclicBarrier(N,new Runnable() {
  11. @Override
  12. public void run() {
  13. System.out.println("线程"+Thread.currentThread().getName()+"正在执行所有线程到达屏障后执行的操作");
  14. }
  15. });
  16. ExecutorService exec=Executors.newFixedThreadPool(4);
  17. for(int i=0;i<N;++i) {
  18. Runnable r=()->{
  19. try {
  20. System.out.println("线程"+Thread.currentThread().getName()+"正在执行线程的操作");
  21. //用睡眠代替线程的操作
  22. Thread.sleep(new Random().nextInt(1000));
  23. System.out.println("线程"+Thread.currentThread().getName()+"到达屏障");
  24. cyclicBarrier.await();
  25. System.out.println("线程"+Thread.currentThread().getName()+"越过屏障,线程执行完毕");
  26. } catch (InterruptedException e) {
  27. e.printStackTrace();
  28. } catch (BrokenBarrierException e) {
  29. e.printStackTrace();
  30. }
  31. };
  32. exec.submit(r);
  33. }
  34. exec.shutdown();
  35. }
  36. }

是否可以重用

  1. CountDownLatch不可以重用

  2. CyclicBarrier可以重用

  1. package cyclicBarrier;
  2. import java.util.Random;
  3. import java.util.concurrent.BrokenBarrierException;
  4. import java.util.concurrent.CyclicBarrier;
  5. import java.util.concurrent.ExecutorService;
  6. import java.util.concurrent.Executors;
  7. public class CyclicBarrierDemo {
  8. public static void main(String[] args) {
  9. int N=4;
  10. CyclicBarrier cyclicBarrier=new CyclicBarrier(N,new Runnable() {
  11. @Override
  12. public void run() {
  13. System.out.println("线程"+Thread.currentThread().getName()+"正在执行所有线程到达屏障后执行的操作");
  14. }
  15. });
  16. ExecutorService exec1=Executors.newFixedThreadPool(4);
  17. for(int i=0;i<N;++i) {
  18. Runnable r=()->{
  19. try {
  20. System.out.println("线程"+Thread.currentThread().getName()+"正在执行线程的操作");
  21. //用睡眠代替线程的操作
  22. Thread.sleep(new Random().nextInt(1000));
  23. System.out.println("线程"+Thread.currentThread().getName()+"到达屏障");
  24. cyclicBarrier.await();
  25. System.out.println("线程"+Thread.currentThread().getName()+"越过屏障,线程执行完毕");
  26. } catch (InterruptedException e) {
  27. e.printStackTrace();
  28. } catch (BrokenBarrierException e) {
  29. e.printStackTrace();
  30. }
  31. };
  32. exec1.submit(r);
  33. }
  34. exec1.shutdown();
  35. try {
  36. Thread.sleep(5000);
  37. } catch (InterruptedException e) {
  38. e.printStackTrace();
  39. }
  40. System.out.println("CyclicBarrier重用");
  41. ExecutorService exec2=Executors.newFixedThreadPool(4);
  42. for(int i=0;i<N;++i) {
  43. Runnable r=()->{
  44. try {
  45. System.out.println("线程"+Thread.currentThread().getName()+"正在执行线程的操作");
  46. //用睡眠代替线程的操作
  47. Thread.sleep(new Random().nextInt(1000));
  48. System.out.println("线程"+Thread.currentThread().getName()+"到达屏障");
  49. cyclicBarrier.await();
  50. System.out.println("线程"+Thread.currentThread().getName()+"越过屏障,线程执行完毕");
  51. } catch (InterruptedException e) {
  52. e.printStackTrace();
  53. } catch (BrokenBarrierException e) {
  54. e.printStackTrace();
  55. }
  56. };
  57. exec2.submit(r);
  58. }
  59. exec2.shutdown();
  60. }
  61. }

CyclicBarrier与CountDownLatch区别的更多相关文章

  1. CyclicBarrier和CountDownLatch区别

    这两天写多线程时,用到了CyclicBarrier,下意识的认为CyclicBarrier和CountDownLatch作用很像,就翻阅资料查了一下,说一下他们的区别吧 CyclicBarrier和C ...

  2. JAVA多线程提高十:同步工具CyclicBarrier与CountDownLatch

    今天继续学习其它的同步工具:CyclicBarrier与CountDownLatch 一.CyclicBarrier CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公 ...

  3. JAVA多线程学习十三 - 同步工具CyclicBarrier与CountDownLatch

    一.CyclicBarrier CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point).在涉及一组固定大小的线程的程序 ...

  4. CountDownLatch、CyclicBarrier、Semaphore 区别

    CountDownLatch.CyclicBarrier.Semaphore 区别: CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不同: Coun ...

  5. JDK源码分析之concurrent包(四) -- CyclicBarrier与CountDownLatch

    上一篇我们主要通过ExecutorCompletionService与FutureTask类的源码,对Future模型体系的原理做了了解,本篇开始解读concurrent包中的工具类的源码.首先来看两 ...

  6. CyclicBarrier和CountDownLatch的差别

    CyclicBarrier和CountDownLatch都用多个线程之间的同步,共同点:同时有N个线程在 CyclicBarrier(CountDownLatch) 等待上等待时,CyclicBarr ...

  7. Java并发之CyclicBarrier、CountDownLatch、Phaser

    在Java多线程编程中,经常会需要我们控制并发流程,等其他线程执行完毕,或者分阶段执行.Java在1.5的juc中引入了CountDownLatch和CyclicBarrier,1.7中又引入了Pha ...

  8. 《java.util.concurrent 包源码阅读》21 CyclicBarrier和CountDownLatch

    CyclicBarrier是一个用于线程同步的辅助类,它允许一组线程等待彼此,直到所有线程都到达集合点,然后执行某个设定的任务. 现实中有个很好的例子来形容:几个人约定了某个地方集中,然后一起出发去旅 ...

  9. 使用数据库乐观锁解决高并发秒杀问题,以及如何模拟高并发的场景,CyclicBarrier和CountDownLatch类的用法

    数据库:mysql 数据库的乐观锁:一般通过数据表加version来实现,相对于悲观锁的话,更能省数据库性能,废话不多说,直接看代码 第一步: 建立数据库表: CREATE TABLE `skill_ ...

随机推荐

  1. 【Javascript函数】节流throttle和间隔控制dbounce

    一.throttle 函数节流,指把很小时间内触发的N多事件,节流成1个事件. 我们这里说的throttle就是函数节流的意思.再说的通俗一点就是函数调用的频度控制器,是连续执行时间间隔控制.主要应用 ...

  2. C#调用JS的WebService的方法返回null

    连上了别人的VPN后,使用WebService测试软件测试了一下,结果正常,但是当我在vs里面添加WebService服务,调用的时候就出现了问题,问题如下图: 后来问了一下服务端那边的同事,他们说服 ...

  3. 自定义实现的ArrayList以及自定义实现的Iterator迭代器

    ArrayList的底层是长度可动态变化的数组,其适用于查找多,修改少的情况,原因是数组的元素的增加删除元素会涉及大量元素的移动,效率比较低,ArrayList中的元素可以重复,与插入时的顺序相同,可 ...

  4. 修饰符new与override

    new:在作为修饰符时,可以隐藏从父类的继承的成员. override:修改父类的方法.属性. 上代码比较清楚: using System; using System.Collections.Gene ...

  5. Redis-缓存穿透、缓存雪崩、缓存击穿、缓存一致性、并发竞争

    缓存流程 在讲这五个问题之前,首先我们回顾下正常的缓存的使用流程 程序在处理请求时,会先从缓存中进行查询,如果缓存中没有对应的key,则会从数据库中查询,如果查询到结果,并将查询结果添加到缓存中去,反 ...

  6. 进一步学习 nox 教程,轻松掌握命令行用法

    英文 |Command-line usage 出处 | nox 官方文档 译者 | 豌豆花下猫@Python猫 Github地址:https://github.com/chinesehuazhou/n ...

  7. 沈阳网络赛 F - 上下界网络流

    "Oh, There is a bipartite graph.""Make it Fantastic." X wants to check whether a ...

  8. dubbo配置文件解读(2)

    <dubbo:service/> <dubbo:reference/> <dubbo:protocol/> <dubbo:registry/> < ...

  9. 函数组合的 N 种模式

    随着以函数即服务(Function as a Service)为代表的无服务器计算(Serverless)的广泛使用,很多用户遇到了涉及多个函数的场景,需要组合多个函数来共同完成一个业务目标,这正是微 ...

  10. App的基本结构

    今天主要学习安装了Android Studio,并且成功地在虚拟机上运行了HelloWord工程.下面针对HelloWord工程对app的基本框架结构进行一个总结.掌握app的基本结构对初学软件开发的 ...