Java多线程-CyclicBarrier

介绍

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

CyclicBarrier 支持一个可选的 Runnable 命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。若在继续所有参与线程之前更新共享状态,此屏障操作 很有用。

主要方法

//设置parties、count及barrierCommand属性。 
CyclicBarrier(int): 
//当await的数量到达了设定的数量后,首先执行该Runnable对象。 
CyclicBarrier(int,Runnable): 
//通知barrier已完成线程 
await():

应用场景

1:CyclicBarrier 表示大家彼此等待,大家集合好后才开始出发,分散活动后又在i指定地点集合碰面,这就好比整个公司的人员利用周末时间集体郊游一样,先各自从家出发到公司集合后,再同时出发到公园游玩,在指定地点集合后再同时开始就餐。

代码:

public class CyclicBarrierTest {
    public static void main(String[] args){
        ExecutorService pool = Executors.newCachedThreadPool();
        final CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
       
        for (int i = 0; i < 3; i++) {
            Runnable runnable = new Runnable() {
                @Override
                public void run(){
                    try {
                        Thread.sleep(new Random().nextInt(5000));
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"到达地点一,当前等待人数为"+(cyclicBarrier.getNumberWaiting()+1)+(cyclicBarrier.getNumberWaiting()+1==3?"继续出发":"继续等待"));
                    try {
                        cyclicBarrier.await();//障碍等待点
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    try {
                        Thread.sleep(new Random().nextInt(5000));
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"到达地点二,当前等待人数为"+(cyclicBarrier.getNumberWaiting()+1)+(cyclicBarrier.getNumberWaiting()+1==3?"继续出发":"继续等待"));
                    try {
                        cyclicBarrier.await();//障碍等待点
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    try {
                        Thread.sleep(new Random().nextInt(5000));
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"到达地点三,当前等待人数为"+(cyclicBarrier.getNumberWaiting()+1)+(cyclicBarrier.getNumberWaiting()+1==3?"人齐了出发":"继续等待"));
                    try {
                        cyclicBarrier.await();//障碍等待点
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            };
            pool.execute(runnable);
        }
        pool.shutdown();
    }
}

执行结果:

pool-1-thread-3到达地点一,当前等待人数为1继续等待
pool-1-thread-1到达地点一,当前等待人数为2继续等待
pool-1-thread-2到达地点一,当前等待人数为3继续出发
pool-1-thread-1到达地点二,当前等待人数为1继续等待
pool-1-thread-3到达地点二,当前等待人数为2继续等待
pool-1-thread-2到达地点二,当前等待人数为3继续出发
pool-1-thread-3到达地点三,当前等待人数为1继续等待
pool-1-thread-2到达地点三,当前等待人数为2继续等待
pool-1-thread-1到达地点三,当前等待人数为3人齐了出发

扫描二维码关注公众号,回复: 2042344 查看本文章

2:在某种需求中,比如一个大型的任务,常常需要分配好多子任务去执行,只有当所有子任务都执行完成时候,才能执行主任务,这时候,就可以选择CyclicBarrier了。

代码:

public class CyclicBarrierTest1 {
    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newCachedThreadPool();
        CyclicBarrier barrier = new CyclicBarrier(5, new mainTask());
        for (int i = 0; i < 5; i++) {
            subTask subTask = new subTask(barrier);
            threadPool.execute(subTask);
        }
        threadPool.shutdown();
    }
}

class subTask implements Runnable{
    private CyclicBarrier barrier;
   
    public subTask(CyclicBarrier barrier) {
        super();
        this.barrier = barrier;
    }
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"正在执行");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"执行完毕,等待其他结果");
        try {
            barrier.await();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
       
    }
}
class mainTask implements Runnable{

    @Override
    public void run() {
        System.out.println("总任务执行完毕");
    }
   
}

执行结果:

pool-1-thread-2正在执行
pool-1-thread-3正在执行
pool-1-thread-1正在执行
pool-1-thread-4正在执行
pool-1-thread-5正在执行
pool-1-thread-2执行完毕,等待其他结果
pool-1-thread-5执行完毕,等待其他结果
pool-1-thread-1执行完毕,等待其他结果
pool-1-thread-4执行完毕,等待其他结果
pool-1-thread-3执行完毕,等待其他结果
总任务执行完毕

另外,CyclicBarrier是可以重用的,它可以在使用完后继续使用,这就是Cyclic(循环)的意思。

猜你喜欢

转载自www.linuxidc.com/Linux/2016-02/128681.htm