JAVA并发,CyclicBarrier

CyclicBarrier 翻译过来叫循环栅栏、循环障碍什么的(还是有点别扭的。所以还是别翻译了,只可意会不可言传啊)。它主要的方法就是一个:await()。await() 方法没被调用一次,计数便会减少1,并阻塞住当前线程。当计数减至0时,阻塞解除,所有在此 CyclicBarrier 上面阻塞的线程开始运行。在这之后,如果再次调用 await() 方法,计数就又会变成 N-1,新一轮重新开始,这便是 Cyclic 的含义所在。

CyclicBarrier 的使用并不难,但需要主要它所相关的异常。除了常见的异常,CyclicBarrier.await() 方法会抛出一个独有的 BrokenBarrierException。这个异常发生在当某个线程在等待本 CyclicBarrier 时被中断或超时或被重置时,其它同样在这个 CyclicBarrier 上等待的线程便会受到 BrokenBarrierException。意思就是说,同志们,别等了,有个小伙伴已经挂了,咱们如果继续等有可能会一直等下去,所有各回各家吧。

CyclicBarrier.await() 方法带有返回值,用来表示当前线程是第几个到达这个 Barrier 的线程。

和 CountDownLatch 一样,CyclicBarrier 同样可以可以在构造函数中设定总计数值。与 CountDownLatch 不同的是,CyclicBarrier 的构造函数还可以接受一个 Runnable,会在 CyclicBarrier 被释放时执行。

“NOTE: CyclicBarrier 的功能也可以由 CountDownLatch 来实现

上面的内容参考自:http://developer.51cto.com/art/201403/432095.htm

下面的例子引用thinking in java(网络上的简单例子体现不出CyclicBarrier存在的意义,和CountDownLatch的用处差不多)

  1 package com.xt.thinks21_7;
  2
  3 //: concurrency/HorseRace.java
  4 // Using CyclicBarriers.
  5 import java.util.concurrent.*;
  6 import java.util.*;
  7
  8 /**
  9  * 马儿类
 10  * @author Administrator
 11  *
 12  */
 13 class Horse implements Runnable {
 14     private static int counter = 0;
 15     private final int id = counter++;
 16     private int strides = 0;
 17     private static Random rand = new Random(47);
 18     private static CyclicBarrier barrier;
 19
 20     public Horse(CyclicBarrier b) {
 21         barrier = b;
 22     }
 23
 24     public synchronized int getStrides() {
 25         return strides;
 26     }
 27
 28     public void run() {
 29         try {
 30             while (!Thread.interrupted()) {
 31                 synchronized (this) {
 32                     //马儿奔跑的不熟,可能是0步,1步,2步
 33                     strides += rand.nextInt(3); // Produces 0, 1 or 2
 34                 }
 35                 //当前线程加入
 36                 barrier.await();
 37                 /*
 38                  * await的源码
 39                  *  public int await() throws InterruptedException, BrokenBarrierException {
 40                         try {
 41                             return dowait(false, 0L);
 42                         } catch (TimeoutException toe) {
 43                             throw new Error(toe); // cannot happen
 44                         }
 45                     }
 46
 47                     dowait的源码:
 48                     private int dowait(boolean timed, long nanos)
 49                         throws InterruptedException, BrokenBarrierException,
 50                                TimeoutException {
 51                         final ReentrantLock lock = this.lock;
 52                         lock.lock();
 53                         try {
 54                             final Generation g = generation;
 55
 56                             if (g.broken)
 57                                 throw new BrokenBarrierException();
 58
 59                             if (Thread.interrupted()) {
 60                                 breakBarrier();
 61                                 throw new InterruptedException();
 62                             }
 63
 64                             int index = --count;
 65                             if (index == 0) {  // tripped
 66                                 boolean ranAction = false;
 67                                 try {
 68                                     final Runnable command = barrierCommand;
 69                                      */
 70
 71                 //这里需要注意,判断了CyclicBarrier构造器中的runnable接口是否为空,不为空回调run方法
 72 //                                    if (command != null)
 73 //                                        command.run();
 74
 75                                     /*
 76                                     ranAction = true;
 77                                     nextGeneration();
 78                                     return 0;
 79                                 } finally {
 80                                     if (!ranAction)
 81                                         breakBarrier();
 82                                 }
 83                             }
 84
 85                             // loop until tripped, broken, interrupted, or timed out
 86                             for (;;) {
 87                                 try {
 88                                     if (!timed)
 89                                         trip.await();
 90                                     else if (nanos > 0L)
 91                                         nanos = trip.awaitNanos(nanos);
 92                                 } catch (InterruptedException ie) {
 93                                     if (g == generation && ! g.broken) {
 94                                         breakBarrier();
 95                                         throw ie;
 96                                     } else {
 97                                         // We‘re about to finish waiting even if we had not
 98                                         // been interrupted, so this interrupt is deemed to
 99                                         // "belong" to subsequent execution.
100                                         Thread.currentThread().interrupt();
101                                     }
102                                 }
103
104                                 if (g.broken)
105                                     throw new BrokenBarrierException();
106
107                                 if (g != generation)
108                                     return index;
109
110                                 if (timed && nanos <= 0L) {
111                                     breakBarrier();
112                                     throw new TimeoutException();
113                                 }
114                             }
115                         } finally {
116                             lock.unlock();
117                         }
118                  */
119             }
120         } catch (InterruptedException e) {
121             // A legitimate way to exit
122         } catch (BrokenBarrierException e) {
123             // This one we want to know about
124             throw new RuntimeException(e);
125         }
126     }
127
128     /**
129      * 打印马儿id
130      */
131     public String toString() {
132         return "Horse " + id + " ";
133     }
134
135     /**
136      * 打印马儿奔跑轨迹
137      */
138     public String tracks() {
139         StringBuilder s = new StringBuilder();
140         for (int i = 0; i < getStrides(); i++)
141             s.append("*");
142         s.append(id);
143         return s.toString();
144     }
145 }
146
147 /**
148  * 马儿奔跑的类
149  * @author Administrator
150  *
151  */
152 public class HorseRace {
153     static final int FINISH_LINE = 75;
154     private List<Horse> horses = new ArrayList<Horse>();
155     private ExecutorService exec = Executors.newCachedThreadPool();
156     private CyclicBarrier barrier;
157
158     public HorseRace(int nHorses, final int pause) {
159         //CyclicBarrier构造器,第二个参数为回调接口,触发条件是await计数到0的时候,也就是所有线程已经加入CyclicBarrier
160         barrier = new CyclicBarrier(nHorses, new Runnable() {
161             public void run() {
162                 StringBuilder s = new StringBuilder();
163                 //打印栅栏
164                 for (int i = 0; i < FINISH_LINE; i++)
165                     s.append("="); // The fence on the racetrack
166                 System.out.println(s);
167                 //打印所有马儿的奔跑轨迹
168                 for (Horse horse : horses)
169                     System.out.println(horse.tracks());
170                 //如果有一个马儿奔跑到了终点,则取消执行器执行所有线程了
171                 for (Horse horse : horses)
172                     if (horse.getStrides() >= FINISH_LINE) {
173                         System.out.print(horse + "won!");
174                         exec.shutdownNow();
175                         return;
176                     }
177                 //每一次所有马儿奔跑一次之后休眠时间
178                 try {
179                     TimeUnit.MILLISECONDS.sleep(pause);
180                 } catch (InterruptedException e) {
181                     System.out.println("barrier-action sleep interrupted");
182                 }
183             }
184         });
185         //加入所有马儿到线程列表,执行器执行线程列表(所有马儿奔跑)
186         for (int i = 0; i < nHorses; i++) {
187             Horse horse = new Horse(barrier);
188             horses.add(horse);
189             exec.execute(horse);
190         }
191     }
192
193     public static void main(String[] args) {
194         int nHorses = 7;
195         int pause = 200;
196         if (args.length > 0) { // Optional argument
197             int n = new Integer(args[0]);
198             nHorses = n > 0 ? n : nHorses;
199         }
200         if (args.length > 1) { // Optional argument
201             int p = new Integer(args[1]);
202             pause = p > -1 ? p : pause;
203         }
204         new HorseRace(nHorses, pause);
205
206     }
207 } /* (Execute to see output) */// :~

总结:

thinking in java上面的代码例子都是精华,不是网络上一般的博主能够写出来的,理解了对自己很有好处,及时一个知识点花上一个小时也可以。

但是美中不足的是:thinking in java中翻译过来有些地方阐述的不是很清楚(可能也是原著就没阐述清楚),例如。它主要的方法就是一个:await()。await() 方法没被调用一次,计数便会减少1,并阻塞住当前线程。当计数减至0时,阻塞解除,所有在此 CyclicBarrier 上面阻塞的线程开始运行。在这之后,如果再次调用 await() 方法,计数就又会变成 N-1,新一轮重新开始,这便是 Cyclic 的含义所在。这段话对CyclicBarrier的理解太重要了我认为。

时间: 2024-08-06 10:21:29

JAVA并发,CyclicBarrier的相关文章

Java并发工具类(二)同步屏障CyclicBarrier

作用 CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point),才继续执行. 简介 CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier).它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活.CyclicBarrier默认的构造方法是CyclicBarrier(int parties),其参数

java并发编程中CountDownLatch和CyclicBarrier的使用

转自:http://blog.csdn.net/hbzyaxiu520/article/details/6183714 在多线程程序设计中,经常会遇到一个线程等待一个或多个线程的场景,遇到这样的场景应该如何解决? 如果是一个线程等待一个线程,则可以通过await()和notify()来实现: 如果是一个线程等待多个线程,则就可以使用CountDownLatch和CyclicBarrier来实现比较好的控制. 下面来详细描述下CountDownLatch的应用场景: 例如:百米赛跑:8名运动员同时

【Java并发编程实战】—–“J.U.C”:CyclicBarrier

在上篇博客([Java并发编程实战]-–"J.U.C":Semaphore)中,LZ介绍了Semaphore,下面LZ介绍CyclicBarrier.在JDK API中是这么介绍的: 一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point).在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用.因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier. Cy

Java并发工具类CyclicBarrier

CyclicBarrier同步屏障 java并发工具类中有一个叫做CyclicBarrier的类,与CountDownLatch类似,都可以实现线程间的同步,但是差别是CyclicBarrier是可重置的同步屏障. 想象一个场景,有N个人不同时间走到一扇门,因为门需要N个人合力才能推开,所以人不足N个时,只能阻塞在此,等到N个人都到了之后,可以推开门,继续进行之前的工作.CyclicBarrier就是这扇门. 看看下面的代码,定义了一个线程数为2的,CyclicBarrier,并在主线程和另外一

Java并发编程:CountDownLatch、CyclicBarrier和Semaphore (总结)

下面对上面说的三个辅助类进行一个总结: 1)CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不同: CountDownLatch一般用于某个线程A等待若干个其他线程执行完任务之后,它才执行: 而CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行: 另外,CountDownLatch是不能够重用的,而CyclicBarrier是可以重用的. 2)Semaphore其实和锁有点类似,它一般用于控制对某组资源的访问权

25.大白话说java并发工具类-CountDownLatch,CyclicBarrier,Semaphore,Exchanger

1. 倒计时器CountDownLatch 在多线程协作完成业务功能时,有时候需要等待其他多个线程完成任务之后,主线程才能继续往下执行业务功能,在这种的业务场景下,通常可以使用Thread类的join方法,让主线程等待被join的线程执行完之后,主线程才能继续往下执行.当然,使用线程间消息通信机制也可以完成.其实,java并发工具类中为我们提供了类似"倒计时"这样的工具类,可以十分方便的完成所说的这种业务场景. 为了能够理解CountDownLatch,举一个很通俗的例子,运动员进行跑

Java并发编程之-了解CyclicBarrier

起因:一道面试题,关于concurrent包下的CyclicBarrier并发工具类,提出的一个情景题,因为不了解,所以花了一天的时间去学习并以此记录而诞生的这篇博客. 题目:假设有5个运动员(线程),让他们就绪在同一位置开始比赛跑步,当裁判(主线程)发出枪响号令.5个运动员(5个线程执行)开始奔跑,当5个线程跑到终点后.裁判(主线程执行)宣布比赛结果. 知识点:CyclicBarrier,CountDownLatch这两个位于JDK concurren包下的两个类.今天只实现CyclicBar

Java 并发工具CountDownLatch和CyclicBarrier 原理解析

[TOC] Java 并发工具CountDownLatch和CyclicBarrier 原理解析 一,简介 CountDownLatch 允许一个或者多个线程等待其他线程完成操作. CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier).它要做的事情是,让一组线程达到一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续运行. 二,代码演示 CountDownLatchDemo public class Co

Java并发编程小总结:CountDownLatch、CyclicBarrier和Semaphore

Java并发编程小总结:CountDownLatch.CyclicBarrier和Semaphore这几个类都是在JUC下,也就是java.util.concurrent包下.这两天学习了一下并发编程中的三个类的使用和一些应用场景,所以做一下记录和总结,方便自己日后再查看复现. 1.CountDownLatch.这个类的核心思想总结为8个字“秦灭6国,一统华夏”.它可以实现的是一个类似计数器的功能,与CyclicBarrier的思想正好相反.是一个减法操作.CountDownLatch有且只有一

Java并发编程笔记 并发概览

并发概览 >>同步 如何同步多个线程对共享资源的访问是多线程编程中最基本的问题之一.当多个线程并发访问共享数据时会出现数据处于计算中间状态或者不一致的问题,从而影响到程序的正确运行.我们通常把这种情况叫做竞争条件(race condition),把并发访问共享数据的代码叫做关键区域(critical section).同步就是使得多个线程顺序进入关键区域从而避免竞争条件的发生. >>线程安全性 编写线程安全的代码的核心是要对状态访问操作进行管理,尤其是对共享的和可变的状态访问. 线