zoukankan      html  css  js  c++  java
  • Java之CyclicBarrier使用

    1、类说明:

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

    2、使用场景:

    需要所有的子任务都完成时,才执行主任务,这个时候就可以选择使用CyclicBarrier。

    实现原理:在CyclicBarrier的内部定义了一个Lock对象,每当一个线程调用CyclicBarrier的await方法时,将剩余拦截的线程数减1,然后判断剩余拦截数是否为0,如果不是,进入Lock对象的条件队列等待。如果是,执行barrierAction对象的Runnable方法,然后将锁的条件队列中的所有线程放入锁等待队列中,这些线程会依次的获取锁、释放锁,接着先从await方法返回,再从CyclicBarrier的await方法中返回。

    3、常用方法:
    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()
    将屏障重置为其初始状态。

    await

    public int await()
              throws InterruptedException,
                     BrokenBarrierException
    在所有参与者都已经在此 barrier 上调用 await方法之前,将一直等待。如果当前线程不是将到达的最后一个线程,出于调度目的,将禁用它,且在发生以下情况之一前,该线程将一直处于休眠状态:

     

    • 最后一个线程到达;或者
    • 其他某个线程中断当前线程;或者
    • 其他某个线程中断另一个等待线程;或者
    • 其他某个线程在等待 barrier 时超时;或者
    • 其他某个线程在此 barrier 上调用 reset()

     

    • 在进入此方法时已经设置了该线程的中断状态;或者
    • 在等待时被中断

    InterruptedException,并且清除当前线程的已中断状态。如果在线程处于等待状态时 barrier 被 reset(),或者在调用 await 时 barrier 被损坏,抑或任意一个线程正处于等待状态,则抛出 BrokenBarrierException 异常。

    中断,则其他所有等待线程都将抛出 BrokenBarrierException 异常,并将 barrier 置于损坏状态。

     

    返回:
    到达的当前线程的索引,其中,索引 getParties() - 1 指示将到达的第一个线程,零指示最后一个到达的线程
    抛出:
    InterruptedException - 如果当前线程在等待时被中断
    BrokenBarrierException - 如果另一个 线程在当前线程等待时被中断或超时,或者重置了 barrier,或者在调用 await 时 barrier 被损坏,抑或由于异常而导致屏障操作(如果存在)失败。
    4、相关实例

    赛跑时,等待所有人都准备好时,才起跑:

    1. public class CyclicBarrierTest {  
    2.   
    3.     public static void main(String[] args) throws IOException, InterruptedException {  
    4.         //如果将参数改为4,但是下面只加入了3个选手,这永远等待下去  
    5.         //Waits until all parties have invoked await on this barrier.   
    6.         CyclicBarrier barrier = new CyclicBarrier(3);  
    7.   
    8.         ExecutorService executor = Executors.newFixedThreadPool(3);  
    9.         executor.submit(new Thread(new Runner(barrier, "1号选手")));  
    10.         executor.submit(new Thread(new Runner(barrier, "2号选手")));  
    11.         executor.submit(new Thread(new Runner(barrier, "3号选手")));  
    12.   
    13.         executor.shutdown();  
    14.     }  
    15. }  
    16.   
    17. class Runner implements Runnable {  
    18.     // 一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)  
    19.     private CyclicBarrier barrier;  
    20.   
    21.     private String name;  
    22.   
    23.     public Runner(CyclicBarrier barrier, String name) {  
    24.         super();  
    25.         this.barrier = barrier;  
    26.         this.name = name;  
    27.     }  
    28.   
    29.     @Override  
    30.     public void run() {  
    31.         try {  
    32.             Thread.sleep(1000 * (new Random()).nextInt(8));  
    33.             System.out.println(name + " 准备好了...");  
    34.             // barrier的await方法,在所有参与者都已经在此 barrier 上调用 await 方法之前,将一直等待。  
    35.             barrier.await();  
    36.         } catch (InterruptedException e) {  
    37.             e.printStackTrace();  
    38.         } catch (BrokenBarrierException e) {  
    39.             e.printStackTrace();  
    40.         }  
    41.         System.out.println(name + " 起跑!");  
    42.     }  
    43. }  


    输出结果:
    3号选手 准备好了...
    2号选手 准备好了...
    1号选手 准备好了...
    1号选手 起跑!
    2号选手 起跑!
    3号选手 起跑!

    public class TestCyclicBarrier {

            private static final int THREAD_NUM = 5;
            
            public static class WorkerThread implements Runnable{

                CyclicBarrier barrier;
                
                public WorkerThread(CyclicBarrier b){
                    this.barrier = b;
                }
                
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    try{
                        System.out.println("Worker's waiting");
                        //线程在这里等待,直到所有线程都到达barrier。
                        barrier.await();
                        System.out.println("ID:"+Thread.currentThread().getId()+" Working");
                    }catch(Exception e){
                        e.printStackTrace();
                    }
                }
                
            }
            
            /**
             * @param args
             */
            public static void main(String[] args) {
                // TODO Auto-generated method stub
                CyclicBarrier cb = new CyclicBarrier(THREAD_NUM, new Runnable() {
                    //当所有线程到达barrier时执行
                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        System.out.println("Inside Barrier");
                        
                    }
                });
                
                for(int i=0;i<THREAD_NUM;i++){
                    new Thread(new WorkerThread(cb)).start();
                }
            }

        }
        /*
        以下是输出:
        Worker's waiting
        Worker's waiting
        Worker's waiting
        Worker's waiting
        Worker's waiting
        Inside Barrier
        ID:12 Working
        ID:8 Working
        ID:11 Working
        ID:9 Working
        ID:10 Working
        */
    1.  CyclicBarrier初始化时规定一个数目,然后计算调用了CyclicBarrier.await()进入等待的线程数。当线程数达到了这个数目时,所有进入等待状态的线程被唤醒并继续。 
    2.  CyclicBarrier就象它名字的意思一样,可看成是个障碍, 所有的线程必须到齐后才能一起通过这个障碍。 
    3.  CyclicBarrier初始时还可带一个Runnable的参数, 此Runnable任务在CyclicBarrier的数目达到后,所有其它线程被唤醒前被执行。
    转载地址:http://www.itzhai.com/the-introduction-and-use-of-cyclicbarrier.html
  • 相关阅读:
    面试题:区分List中remove(int index)和remove(Object obj)
    Collection的子接口之一:List 接口
    面试题:ArrayList、LinkedList、Vector三者的异同?
    jdk 5.0 新增的foreach循环(用于遍历集合、数组)
    Iterator迭代器接口(遍历Collection的两种方式之一)
    哈希值
    Collection接口方法
    集合框架的概述
    注解(Annotation)
    System类、Math类、BigInteger与BigDecimal的使用
  • 原文地址:https://www.cnblogs.com/esther-qing/p/6492247.html
Copyright © 2011-2022 走看看