CyclicBarrier它是一个同步辅助类,允许一组线程互相等待,直到到达某个公共屏障点(common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时CyclicBarrier很有用,常用于协调分组的线程的启动和停止。因为该barrier在释放等待线程后可以重用,屏障可以被重复的重置状态。所以称它为循环的barrier。
CyclicBarrier的构造函数为CyclicBarrier(int parties,Runnable barrierAction):在CyclicBarrier初始化的时候指定参与者的数量,并且支持一个可选的Runnable命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次,并且由最后一个到达屏障的线程执行该屏障点的任务。若在继续所有参与线程之前更新共享状态,此屏障操作很有用。参与者调用awart法进入阻塞状态直到参与者的个数达到指定数量,此时最后一个到达的线程执行预定的屏障任务,然后释放所有的线程。需要注意的是,除了常见的InterruptedException以外,CyclicBarrier 的 await 的方法还会抛出 BrokenBarrierException,这个异常通常发生在CyclicBarrier被重置或者别的阻塞在CyclicBarrier.await()上的线程被打断。同时,CyclicBarrier的await方法带有返回值,可以得到到达屏障处的线程的索引,通俗一点说就是后面还有几个线程没有执行await。注:这里parties里的计数在运行时当调用await()时,计数就加1,一直加到初始的值。
运行结果:
本文转自:http://blog.csdn.net/YJian2008/article/details/16963657
CyclicBarrier的构造函数为CyclicBarrier(int parties,Runnable barrierAction):在CyclicBarrier初始化的时候指定参与者的数量,并且支持一个可选的Runnable命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次,并且由最后一个到达屏障的线程执行该屏障点的任务。若在继续所有参与线程之前更新共享状态,此屏障操作很有用。参与者调用awart法进入阻塞状态直到参与者的个数达到指定数量,此时最后一个到达的线程执行预定的屏障任务,然后释放所有的线程。需要注意的是,除了常见的InterruptedException以外,CyclicBarrier 的 await 的方法还会抛出 BrokenBarrierException,这个异常通常发生在CyclicBarrier被重置或者别的阻塞在CyclicBarrier.await()上的线程被打断。同时,CyclicBarrier的await方法带有返回值,可以得到到达屏障处的线程的索引,通俗一点说就是后面还有几个线程没有执行await。注:这里parties里的计数在运行时当调用await()时,计数就加1,一直加到初始的值。
下面举例说明该类的用法:我们编写一个用于计算ln(1-x)的程序。其中ln为自然对数。计算方式为:ln(1-x)=-(x + x2/2 + x3/3 + x4/4 + x5/5 + ...) where |x| < 1 。我们将创建线程来计算这个级数的每一项。这里只计算10项,所以需要创建10个线程,每个线程将计算结果放入公共数组中,并且在屏障中等待其他线程,当每个线程完成后,最后一个到达的线程完成最后一项的计算并求得总和并显示给用户。
源码如下:
- import java.util.concurrent.BrokenBarrierException;
- import java.util.concurrent.CyclicBarrier;
- public class NaturalLogCalc {
- private static final int numberOfitems = 10;// 计算前十个即可,所以需要十个线程来完成
- // 给个线程将计算结果都放在数组中
- private static double[] termArray = new double[numberOfitems];
- private static final float x = 0.2f;// 计算x的ln值
- public static void main(String[] args) {
- CyclicBarrier barrier = new CyclicBarrier(numberOfitems,
- // 屏障打破后该Runnable就可以执行了,在本例中就是当所有线程将每个项目计算完
- // 成之后屏障就被打破,从而计算每个值之和,即为所求结果
- new Runnable() {
- @Override
- public void run() {
- System.out.println("Computing series sum");
- double sum = 0;
- // 第一项为0.2f,但是经过Math.pow之后就变成了:0.20000000298023224
- for (double term : termArray) {
- sum += term;
- }
- System.out.println("ln(1-" + x + ") equals " + -sum);
- System.out.println(Thread.currentThread().getName());
- }
- });
- for (int i = 0; i < numberOfitems; i++) {
- new Thread(new NaturalLogCalc().new TermCalc(barrier, i), "Thread-"
- + (i + 1)).start();
- }
- System.out.println("Waiting...");
- }
- // 每一个线程执行各自对应的项目,并放入数组中,便于计算总和
- // ln(1-x)=-(x + x2/2 + x3/3 + x4/4 + x5/5 + ...) where |x| < 1
- private class TermCalc implements Runnable {
- private int termIndex;
- private CyclicBarrier barrier;
- public TermCalc(CyclicBarrier barrier, int termIndex) {
- this.barrier = barrier;
- this.termIndex = termIndex;
- }
- @Override
- public void run() {
- double result = Math.pow(x, termIndex + 1) / (termIndex + 1);
- termArray[termIndex] = result;
- System.out.println("Term " + (termIndex + 1) + ":" + result);
- try {
- barrier.await();
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (BrokenBarrierException e) {
- e.printStackTrace();
- }
- }
- }
- }
- Waiting...
- Term 1:0.20000000298023224 //第一项为原始值float类型,计算之后为double,精度变大,所以不再是0.02,而是这个值。
- Term 10:1.0240001525879009E-8
- Term 6:1.0666667620341019E-5
- Term 9:5.688889651828388E-8
- Term 7:1.8285716193063003E-6
- Term 5:6.400000476837173E-5
- Term 2:0.020000000596046452
- Term 8:3.2000003814697465E-7
- Term 4:4.0000002384185847E-4
- <span style="color:#ff0000;">Term 3</span>:0.002666666785875958
- Computing series sum
- ln(1-0.2) equals -0.22314355275894068
- Thread-3//最后一个到达屏障的线程执行总和</span>