java线程栅栏_Java多线程并发系列之闭锁(Latch)和栅栏(CyclicBarrier)

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

1. 闭锁(Latch)

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

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

1 public static void main(String[] args) throwsInterruptedException {2 //申明,等待事件数量 5次

3 CountDownLatch await = new CountDownLatch(5);4

5 //依次创建并启动处于等待状态的5个MyRunnable线程

6 for (int i = 1; i < 6; ++i) {7 new Thread(newMyRunnable(await, i)).start();8 }9

10 System.out.println("等待线程开始工作......");11 await.await();12 System.out.println("结束!");13 }

1 public static class MyRunnable implementsRunnable {2

3 private finalCountDownLatch await;4 private final intnum;5

6 public MyRunnable(CountDownLatch await, intnum) {7 this.await =await;8 this.num =num;9 }10

11 public voidrun() {12 try{13 System.out.println("线程"+num+"执行完毕。");14 await.countDown(); //当前事件执行完毕,计数 -1

15 } catch(InterruptedException e) {16 e.printStackTrace();17 }18 }19 }

运行结果:

等待线程开始工作......

线程1执行完毕。

线程2执行完毕。

线程3执行完毕。

线程4执行完毕。

线程5执行完毕。

结束!

流程如图所示:

f2bfaee2fa567cec5a599e596166610d.png

图1 - CountDownLatch 处理流程

2. 栅栏(CyclicBarrier)

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

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

示例如下:

1 public static void main(String[] args) throwsInterruptedException {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 implementsRunnable {2 private finalCyclicBarrier cyclicBarrier;3 private finalString event;4

5 publicChairRunnable(CyclicBarrier cyclicBarrier, String event) {6 this.cyclicBarrier =cyclicBarrier;7 this.event =event;8 }9

10 public voidrun() {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 }

运行结果:

开始做【椅子腿】。

开始做【椅子背】。

开始做【椅子面】。

【椅子面】做好了, 我们来一起组装吧!

【椅子腿】做好了, 我们来一起组装吧!

【椅子背】做好了, 我们来一起组装吧!

流程如下图所示:

833bf13cac5a14bb8e05d8bde78b66a2.png

图2 - CyclicBarrier 处理流程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值