博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java多线程并发系列之闭锁(Latch)和栅栏(CyclicBarrier)
阅读量:4137 次
发布时间:2019-05-25

本文共 2890 字,大约阅读时间需要 9 分钟。


  

JAVA并发包中有三个类用于同步一批线程的行为,分别是闭锁(Latch),信号灯(Semaphore)和栅栏(CyclicBarrier)。本贴主要说明闭锁(Latch)和栅栏(CyclicBarrier)。

1. 闭锁(Latch)

闭锁(Latch)  —— 确保多个线程在完成各自事务后,才会打开继续执行后面的内容,否则一直等待。

计数器闭锁(CountDownLatch) —— 是JDK5+ 里面闭锁的一个实现,允许一个或多个线程等待某个事件的发生。CountDownLatch  有个正数的计数器,countDown(); 对计数器做减法操作,await(); 等待计数器 = 0。所有await的线程都会阻塞,直到计数器为0或者等待线程中断或者超时。

1 public static void main(String[] args) throws InterruptedException { 2         // 申明,等待事件数量 5次 3         CountDownLatch await = new CountDownLatch(5); 4   5         // 依次创建并启动处于等待状态的5个MyRunnable线程 6         for (int i = 1; i < 6; ++i) { 7             new Thread(new MyRunnable(await, i)).start(); 8         } 9  10         System.out.println("等待线程开始工作......");11         await.await();12         System.out.println("结束!");13 }
1 public static class MyRunnable implements Runnable { 2   3     private final CountDownLatch await; 4     private final int num; 5   6     public MyRunnable(CountDownLatch await, int num) { 7         this.await = await; 8         this.num  =  num; 9     }10  11     public void run() {12         try {13             System.out.println("线程"+num+"执行完毕。");14             await.countDown(); // 当前事件执行完毕,计数 -115         } catch (InterruptedException e) {16             e.printStackTrace();17         }18     }19 }
运行结果:等待线程开始工作......线程1执行完毕。线程2执行完毕。线程3执行完毕。线程4执行完毕。线程5执行完毕。结束!

 

流程如图所示:

 图1 - CountDownLatch 处理流程

 

2. 栅栏(CyclicBarrier)

栅栏类似于闭锁,它能阻塞一组线程直到某个事件发生。 栅栏与闭锁的关键区别在于,所有的线程必须同时到达栅栏位置,才能继续执行。闭锁用于等待事件,而栅栏用于等待其他线程。

场景: 比如甲乙丙三人一把椅子,甲做椅子腿,乙做椅子面,丙做椅子靠背。等3人都做成后,就可以组装成椅子了。这是一种并行迭代,将一个问题分成很多子问题,当一系列的子问题都解决之后(所有子问题线程都已经await(); ),此时将栅栏打开,所有子问题线程被释放,而栅栏位置可以留着下次使用。

 示例如下:

1 public static void main(String[] args) throws InterruptedException {2     // 申明,等待线程数量 3次3     CyclicBarrier cyclicBarrier = new CyclicBarrier(3);4 5     // 依次创建并启动处于等待状态的3个MyRunnable2线程6     new Thread(new ChairRunnable(cyclicBarrier, "椅子腿")).start();7     new Thread(new ChairRunnable(cyclicBarrier, "椅子面")).start();8     new Thread(new ChairRunnable(cyclicBarrier, "椅子背")).start();9 }
1 public static class ChairRunnable implements Runnable { 2     private final CyclicBarrier cyclicBarrier; 3     private final String event; 4  5     public ChairRunnable(CyclicBarrier cyclicBarrier, String event) { 6         this.cyclicBarrier = cyclicBarrier; 7         this.event = event; 8     } 9 10     public void run() {11         try {12             System.out.println("开始做【" + event + "】。");13             Thread.sleep(new Random().nextInt(10000));14             cyclicBarrier.await(); // 等待其他线程完成15         } catch (InterruptedException e) {16             e.printStackTrace();17         } catch (BrokenBarrierException e) {18             e.printStackTrace();19         }20         System.out.println("【" + event + "】做好了, 我们来一起组装吧!");21     }22 }
运行结果:开始做【椅子腿】。开始做【椅子背】。开始做【椅子面】。【椅子面】做好了, 我们来一起组装吧!【椅子腿】做好了, 我们来一起组装吧!【椅子背】做好了, 我们来一起组装吧!

 

流程如下图所示:

图2 - CyclicBarrier 处理流程

 

转载地址:http://fgovi.baihongyu.com/

你可能感兴趣的文章
qt实现点击出现窗口,点击其他任何地方窗口消失
查看>>
QML DropArea拖拉文件事件
查看>>
CORBA links
查看>>
读后感:&gt;
查看>>
ideas about sharing software
查看>>
different aspects for software
查看>>
To do list
查看>>
Study of Source code
查看>>
如何使用BBC英语学习频道
查看>>
spring事务探索
查看>>
浅谈Spring声明式事务管理ThreadLocal和JDKProxy
查看>>
初识xsd
查看>>
java 设计模式-职责型模式
查看>>
构造型模式
查看>>
svn out of date 无法更新到最新版本
查看>>
java杂记
查看>>
RunTime.getRuntime().exec()
查看>>
Oracle 分组排序函数
查看>>
删除weblogic 域
查看>>
VMware Workstation 14中文破解版下载(附密钥)(笔记)
查看>>