CyclicBarrier的用法

标签: cyclicbarrier | 发表时间:2016-07-20 18:23 | 作者:hubowei1
出处:http://www.iteye.com
本例介绍第三个同步装置:CyclicBarrier,它维护一个计数器,与CountDownLatch不同的是,等待这个CyclicBarrier的线程必须等到计数器到达某个值时,才可以继续。CyclicBarrier就像它名字的意思一样,可看成是个障碍,所有的线程必须到齐后才能一起通过这个障碍。本例实现一个数组相邻元素的加法,一个线程给数组的第一个元素赋值,然后等待其他线程给数组第二个元素赋值,然后将第一个元素和第二个元素相加。

       构造CyclicBarrier对象时,需要指定计数器的目标值,计数器的初始值为0.还可以在构造方法中带一个Runnable参数,表示当计数器到达目标值时,在等待CyclicBarrier的线程被唤醒之前,指定该Runnable任务。
       CyclicBarrier的await方法使当前线程进入等待状态,计数器加1,当计数器到达目标值时,当前线程被唤醒。

 

CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。

  CyclicBarrier类似于CountDownLatch也是个计数器, 不同的是CyclicBarrier数的是调用了CyclicBarrier.await()进入等待的线程数, 当线程数达到了CyclicBarrier初始时规定的数目时,所有进入等待状态的线程被唤醒并继续。 CyclicBarrier就象它名字的意思一样,可看成是个障碍, 所有的线程必须到齐后才能一起通过这个障碍。 CyclicBarrier初始时还可带一个Runnable的参数,此Runnable任务在CyclicBarrier的数目达到后,所有其它线程被唤醒前被执行。


构造方法摘要

CyclicBarrier(int parties)
          创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,但它不会在每个 barrier 上执行预定义的操作。
CyclicBarrier(int parties, Runnable barrierAction)
          创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,并在启动 barrier 时执行给定的屏障操作,该操作由最后一个进入 barrier 的线程执行




方法摘要

int await()
          在所有参与者都已经在此 barrier 上调用 await 方法之前,将一直等待。
int await(long timeout, TimeUnit unit)
          在所有参与者都已经在此屏障上调用 await 方法之前,将一直等待。
int getNumberWaiting()
          返回当前在屏障处等待的参与者数目。
int getParties()
          返回要求启动此 barrier 的参与者数目。
boolean isBroken()
          查询此屏障是否处于损坏状态。
void reset()
          将屏障重置为其初始状态。



package com.thread;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class CyclicBarrierTest {

    public static void main(String[] args) {
        ExecutorService service = Executors.newCachedThreadPool();
        final  CyclicBarrier cb = new CyclicBarrier(3);//创建CyclicBarrier对象并设置3个公共屏障点
        for(int i=0;i<3;i++){
            Runnable runnable = new Runnable(){
                    public void run(){
                    try {
                        Thread.sleep((long)(Math.random()*10000));   
                        System.out.println("线程" + Thread.currentThread().getName() +
                                "即将到达集合地点1,当前已有" + cb.getNumberWaiting() + "个已经到达,正在等候");                       
                        cb.await();//到此如果没有达到公共屏障点,则该线程处于等待状态,如果达到公共屏障点则所有处于等待的线程都继续往下运行
                       
                        Thread.sleep((long)(Math.random()*10000));   
                        System.out.println("线程" + Thread.currentThread().getName() +
                                "即将到达集合地点2,当前已有" + cb.getNumberWaiting() + "个已经到达,正在等候");                       
                        cb.await();   
                        Thread.sleep((long)(Math.random()*10000));   
                        System.out.println("线程" + Thread.currentThread().getName() +
                                "即将到达集合地点3,当前已有" + cb.getNumberWaiting() + "个已经到达,正在等候");                       
                        cb.await();                       
                    } catch (Exception e) {
                        e.printStackTrace();
                    }               
                }
            };
            service.execute(runnable);
        }
        service.shutdown();
    }
}



线程pool-1-thread-1即将到达集合地点1,当前已有0个已经到达,正在等候
线程pool-1-thread-3即将到达集合地点1,当前已有1个已经到达,正在等候
线程pool-1-thread-2即将到达集合地点1,当前已有2个已经到达,正在等候
线程pool-1-thread-3即将到达集合地点2,当前已有0个已经到达,正在等候
线程pool-1-thread-2即将到达集合地点2,当前已有1个已经到达,正在等候
线程pool-1-thread-1即将到达集合地点2,当前已有2个已经到达,正在等候
线程pool-1-thread-1即将到达集合地点3,当前已有0个已经到达,正在等候
线程pool-1-thread-3即将到达集合地点3,当前已有1个已经到达,正在等候
线程pool-1-thread-2即将到达集合地点3,当前已有2个已经到达,正在等候



 如果在构造CyclicBarrier对象的时候传了一个Runnable对象进去,则每次到达公共屏障点的时候都最先执行这个传进去的Runnable,然后再执行处于等待的Runnable。如果把上面的例子改成下面这样:

package com.thread;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class CyclicBarrierTest {

    public static void main(String[] args) {
        ExecutorService service = Executors.newCachedThreadPool();
        //final  CyclicBarrier cb = new CyclicBarrier(3);//创建CyclicBarrier对象并设置3个公共屏障点
        final  CyclicBarrier cb = new CyclicBarrier(3,new Runnable(){
            @Override
            public void run() {
                System.out.println("********我最先执行***********");
            }
        });
        for(int i=0;i<3;i++){
            Runnable runnable = new Runnable(){
                    public void run(){
                    try {
                        Thread.sleep((long)(Math.random()*10000));   
                        System.out.println("线程" + Thread.currentThread().getName() +
                                "即将到达集合地点1,当前已有" + cb.getNumberWaiting() + "个已经到达,正在等候");                       
                        cb.await();//到此如果没有达到公共屏障点,则该线程处于等待状态,如果达到公共屏障点则所有处于等待的线程都继续往下运行
                       
                        Thread.sleep((long)(Math.random()*10000));   
                        System.out.println("线程" + Thread.currentThread().getName() +
                                "即将到达集合地点2,当前已有" + cb.getNumberWaiting() + "个已经到达,正在等候");                       
                        cb.await();    //这里CyclicBarrier对象又可以重用
                        Thread.sleep((long)(Math.random()*10000));   
                        System.out.println("线程" + Thread.currentThread().getName() +
                                "即将到达集合地点3,当前已有" + cb.getNumberWaiting() + "个已经到达,正在等候");                       
                        cb.await();                       
                    } catch (Exception e) {
                        e.printStackTrace();
                    }               
                }
            };
            service.execute(runnable);
        }
        service.shutdown();
    }
}



线程pool-1-thread-1即将到达集合地点1,当前已有0个已经到达,正在等候
线程pool-1-thread-3即将到达集合地点1,当前已有1个已经到达,正在等候
线程pool-1-thread-2即将到达集合地点1,当前已有2个已经到达,正在等候
********我最先执行***********
线程pool-1-thread-1即将到达集合地点2,当前已有0个已经到达,正在等候
线程pool-1-thread-3即将到达集合地点2,当前已有1个已经到达,正在等候
线程pool-1-thread-2即将到达集合地点2,当前已有2个已经到达,正在等候
********我最先执行***********
线程pool-1-thread-1即将到达集合地点3,当前已有0个已经到达,正在等候
线程pool-1-thread-3即将到达集合地点3,当前已有1个已经到达,正在等候
线程pool-1-thread-2即将到达集合地点3,当前已有2个已经到达,正在等候
********我最先执行***********




已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [cyclicbarrier] 推荐:

CyclicBarrier的用法

- - 编程语言 - ITeye博客
本例介绍第三个同步装置:CyclicBarrier,它维护一个计数器,与CountDownLatch不同的是,等待这个CyclicBarrier的线程必须等到计数器到达某个值时,才可以继续. CyclicBarrier就像它名字的意思一样,可看成是个障碍,所有的线程必须到齐后才能一起通过这个障碍. 本例实现一个数组相邻元素的加法,一个线程给数组的第一个元素赋值,然后等待其他线程给数组第二个元素赋值,然后将第一个元素和第二个元素相加.

JUC CyclicBarrier 可重用屏障

- - 码蜂笔记
CyclicBarrier 是一个线程同步工具,用于一组互相等待线程之间的协调,在到达某个临界点之前,这些线程必须互相等待,在通过临界点之后,这些线程是独立的;CountDownLatch 是让一个线程等待其他线程完成某些任务,其他线程之间一直是独立的. CyclicBarrier 还允许指定一个任务,在所有线程到达临界点时执行,由最后到达的线程执行此任务.

Java并发工具类CyclicBarrier

- - CSDN博客编程语言推荐文章
CyclicBarrier同步屏障. java并发工具类中有一个叫做CyclicBarrier的类,与CountDownLatch类似,都可以实现线程间的同步,但是差别是CyclicBarrier是可重置的同步屏障. 想象一个场景,有N个人不同时间走到一扇门,因为门需要N个人合力才能推开,所以人不足N个时,只能阻塞在此,等到N个人都到了之后,可以推开门,继续进行之前的工作.