zoukankan      html  css  js  c++  java
  • Java多线程之新类库中的构件CyclicBarrier

    1、类说明:

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

    2、使用场景:

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

    3、常用方法:

    await

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

    如果当前线程:

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

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

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

    如果当前线程是最后一个将要到达的线程,并且构造方法中提供了一个非空的屏障操作,则在允许其他线程继续运行之前,当前线程将运行该操作。如果在执行屏障操作过程中发生异常,则该异常将传播到当前线程中,并将 barrier 置于损坏状态。

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

    演示代码1:

    package concurrent;
    
    import java.util.concurrent.CyclicBarrier;
    
    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:10 Working
    ID:12 Working
    ID:13 Working
    ID:9 Working
    ID:11 Working

    演示代码2:

    package concurrent;
    
    import java.util.Random;  
    import java.util.concurrent.CyclicBarrier;  
      
    /** 
     * CyclicBarrier类似于CountDownLatch也是个计数器, 
     * 不同的是CyclicBarrier数的是调用了CyclicBarrier.await()进入等待的线程数, 
     * 当线程数达到了CyclicBarrier初始时规定的数目时,所有进入等待状态的线程被唤醒并继续。 
     * CyclicBarrier就象它名字的意思一样,可看成是个障碍, 
     * 所有的线程必须到齐后才能一起通过这个障碍。 
     * CyclicBarrier初始时还可带一个Runnable的参数, 
     * 此Runnable任务在CyclicBarrier的数目达到后,所有其它线程被唤醒前被执行。 
     */  
    public class CyclicBarrierTest {  
      
        public static class ComponentThread implements Runnable {  
            CyclicBarrier barrier;// 计数器  
            int ID; // 组件标识  
            int[] array;    // 数据数组  
      
            // 构造方法  
            public ComponentThread(CyclicBarrier barrier, int[] array, int ID) {  
                this.barrier = barrier;  
                this.ID = ID;  
                this.array = array;  
            }  
      
            public void run() {  
                try {  
                    array[ID] = new Random().nextInt(100);  
                    System.out.println("Component " + ID + " generates: " + array[ID]);  
                    // 在这里等待Barrier处  
                    System.out.println("Component " + ID + " sleep...");  
                    barrier.await();  
                    System.out.println("Component " + ID + " awaked...");  
                    // 计算数据数组中的当前值和后续值  
                    int result = array[ID] + array[ID + 1];  
                    System.out.println("Component " + ID + " result: " + result);  
                } catch (Exception ex) {  
                }  
            }  
        }  
        /** 
         * 测试CyclicBarrier的用法 
         */  
        public static void testCyclicBarrier() {  
            final int[] array = new int[3];  
            CyclicBarrier barrier = new CyclicBarrier(2, new Runnable() {  
                // 在所有线程都到达Barrier时执行  
                public void run() {  
                    System.out.println("testCyclicBarrier run...");  
                    array[2] = array[0] + array[1];  
                }  
            });  
      
            // 启动线程  
            new Thread(new ComponentThread(barrier, array, 0)).start();  
            new Thread(new ComponentThread(barrier, array, 1)).start();  
        }  
      
        public static void main(String[] args) {  
            CyclicBarrierTest.testCyclicBarrier();  
        }  
    }  
    Component 0 generates: 87
    Component 0 sleep...
    Component 1 generates: 0
    Component 1 sleep...
    testCyclicBarrier run...
    Component 1 awaked...
    Component 1 result: 87
    Component 0 awaked...
    Component 0 result: 87
  • 相关阅读:
    JS BOM对象 History对象 Location对象
    JS 字符串对象 数组对象 函数对象 函数作用域
    JS 引入方式 基本数据类型 运算符 控制语句 循环 异常
    Pycharm Html CSS JS 快捷方式创建元素
    CSS 内外边距 float positio属性
    CSS 颜色 字体 背景 文本 边框 列表 display属性
    【Android】RxJava的使用(三)转换——map、flatMap
    【Android】RxJava的使用(二)Action
    【Android】RxJava的使用(一)基本用法
    【Android】Retrofit 2.0 的使用
  • 原文地址:https://www.cnblogs.com/zhuawang/p/3783091.html
Copyright © 2011-2022 走看看