java.util.concurrent CyclicBarrier类

JAVA学习网 2017-11-03 00:21:02

CyclicBarrier类:

  原文解释:一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环的 barrier。CyclicBarrier支持一个可选的 Runnable 命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。若在继续所有参与线程之前更新共享状态,此屏障操作 很有用。 

  通俗解释:它可以让多个线程阻塞,调用CyclicBarrier的await()方法让线程一直在等待,直到所有线程都到达屏障后执行你需要的操作,然后线程被唤醒,继续往下执行。

 

CyclicBarrier构造方法:

  CyclicBarrier(int parties)

  CyclicBarrier(int parties, Runnable barrierAction)

  下面的例子使用第二个构造方法,模拟10个狙击手分别就位,如果10个狙击手都已经就位完毕,则报告给指挥官,指挥官下达命令后才能进行射击。

public class Demo {

    public static void main(String[] args) {

        //定义10个狙击手
        int threadNum = 10;

        //实例化一个CyclicBarrier(循环屏障)
        CyclicBarrier cyclicBarrier = new CyclicBarrier(threadNum, new Runnable(){
            @Override
            public void run(){
                System.out.println("负责人:报告指挥官,所有狙击手已就位完毕。");
                System.out.println("指挥官:行动!");
            }
        });

        //模拟加入10个线程
        for(int i=1; i<=threadNum; i++){
            new Thread(new Sniper(cyclicBarrier, "狙击手" + i + "号")).start();
        }
    }
}

  定义一个狙击手的类,并实现Runnable接口。

public class Sniper implements Runnable {

    private CyclicBarrier cyclicBarrier;
    private String name;

    public Sniper(CyclicBarrier cyclicBarrier, String name){
        this.cyclicBarrier = cyclicBarrier;
        this.name = name;
    }

    @Override
    public void run() {
        try {

            //随机0-10秒模拟狙击手就位需要的时间
            Random ran = new Random();
            int millisecond = (ran.nextInt(10) + 1);
            int second = millisecond * 1000;
            Thread.sleep(second);

            //准备好之后,报告已就位
            System.out.println( name + ":已就位,用时" + millisecond + "秒。");

            //调用cyclicBarrier.await()方法进行等待
            cyclicBarrier.await();

            //狙击手打击目标
            System.out.println( name + ":报告," + (millisecond % 2 == 1 ? "已击毙敌人。" : "未命中。"));

        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}

  每个线程在运行到cyclicBarrier.await()方法时,将被阻塞无法继续往下进行,直到所有线程都到达屏障才继续往下执行,CyclicBarrier的构造函数的parties参数指定线程数量,CyclicBarrier内部count变量记录仍需要等待的线程数,每个线程到达屏障后count会减少1,当count=0时,表示没有任何线程需要等待,则执行CyclicBarrier构造函数的barrierAction的run()方法。由此可知,假设有10个线程执行,而CyclicBarrier的parties数量大于线程数,假设parties=12,则导致CyclicBarrier内部的count再所有线程到达屏障后count等于2,而无法唤醒线程,程序则一直再等待。

  从这里可以看出,

  效果如下:

 

阅读(739) 评论(0)