java并发中的CyclicBarrier

来源:互联网 发布:网络写手挣钱么 编辑:程序博客网 时间:2024/06/06 08:30
  • CyclicBarrier介绍:翻译过来就是回旋栅栏。主要适用于这样的场景,你希望创建一组任务,他们并行的执行工作,然后在进行工作下一个步骤之前等待,直至所有任务完成。
    它有两个构造函数:

    public CyclicBarrier(int parties, Runnable barrierAction) {}public CyclicBarrier(int parties) {}

    parties代表一次并行的任务,barrierAction当这些线程都达到barrier状态时要执行的任务,会选择一个线程去执行这个Runnable

    重载了一个方法await()

    public int await() throws InterruptedException, BrokenBarrierException { }
    public int await(long timeout, TimeUnit unit)throws InterruptedException,BrokenBarrierException,TimeoutException { }

    第一个方法用来挂起当前线程,直至所有线程都到达barrier状态再同时执行后续任务。第二个方法是让这些线程等待至一定的时间,如果还有线程没有到达barrier状态就直接让到达barrier的线程执行后续任务。

  • 一个实列
    简单介绍:模拟了一个赛马的过程,每个马都有都有一个栅栏,当执行到runnable方法里,执行完相应的 操作以后,就会调用await()方法将自己挂起,直到所有执行的线程都到达栅栏
    在HorseRace类中,首先先添加参加马赛的马,以及初始化了CyclicBarrier对象

代码如下:
Horse类:

public class Horse implements Runnable {    private static int counter = 0;    private final int id = counter++;    private int strides = 0;    private static Random rand = new Random(47);    private static CyclicBarrier barrier;    public Horse(CyclicBarrier b) { barrier = b; }    public synchronized int getStrides() { return strides; }    public void run() {        try {            while(!Thread.interrupted()) {                synchronized(this) {                    strides += rand.nextInt(3); // Produces 0, 1 or 2                }                barrier.await();  //在栅栏处等待            }        } catch(InterruptedException e) {            // A legitimate way to exit        } catch(BrokenBarrierException e) {            // This one we want to know about            throw new RuntimeException(e);        }    }    public String toString() { return "Horse " + id + " "; }    public String tracks() {        StringBuilder s = new StringBuilder();        for(int i = 0; i < getStrides(); i++)            s.append("*");        s.append(id);        return s.toString();    }} 

HorseRace类:

public class HorseRace {    static final int FINISH_LINE = 75;    private List<Horse> horses = new ArrayList<Horse>();    private ExecutorService exec =            Executors.newCachedThreadPool();    private CyclicBarrier barrier;    public HorseRace(int nHorses, final int pause) {        barrier = new CyclicBarrier(nHorses, new Runnable() {            public void run() {                System.out.println("执行runnable方法的线程: " + Thread.currentThread().getName());                StringBuilder s = new StringBuilder();                for(int i = 0; i < FINISH_LINE; i++)                    s.append("="); // The fence on the racetrack                System.out.println(s);                for(Horse horse : horses)                    System.out.println(horse.tracks());                for(Horse horse : horses)                    if(horse.getStrides() >= FINISH_LINE) {                        System.out.println(horse + "won!");                        exec.shutdownNow();                        return;                    }                try {                    TimeUnit.MILLISECONDS.sleep(pause);                } catch(InterruptedException e) {                    System.out.println("barrier-action sleep interrupted");                }            }        });        for(int i = 0; i < nHorses; i++) {            Horse horse = new Horse(barrier);            horses.add(horse);            exec.execute(horse);        }    }    public static void main(String[] args) {        int nHorses = 7;        int pause = 200;        new HorseRace(nHorses, pause);    }}

为了看是否只选择了一个线程去执行Runnable,在HorseRace中打印了一下当前的线程的名字,从结果来看确实是这样的。

原创粉丝点击