zoukankan      html  css  js  c++  java
  • Java并发工具类之同步屏障CyclicBarrier

      CyclicBarrier的字面意思是可以循环使用的Barrier,它要做的事情是让一个线程到达一个Barrier的时候被阻塞,直到最后一个线程到达Barrier,屏障才会放开,所有被Barrier拦截的线程才会继续运行。

      CyclicBarrier的默认的构造器是CyclicBarrier(int parties),参数表示屏障拦截的线程数量,每个线程调用await方法告诉CyclicBarrier我已经到达了屏障,然后当前线程被阻塞。示例代码如下:

      

    public class CyclicBarrierTest {
    
        private static CyclicBarrier barrier = new CyclicBarrier(2);
    
        public static void main(String[] args) throws BrokenBarrierException, InterruptedException {
    
            new Thread(new Runnable() {
    
                @Override
                public void run() {
                    try {
                        barrier.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                    System.out.print("thread1");
                }
    
            }).start();
    
            barrier.await();
    
            System.out.println("mainThread");
        }
    }

      因为子线程和主线程的调度由CPU决定,每个线程都有可能优先执行,因此会产生两种不同的结果,可能的结果如下:

      mainThread
      thread1

      如果把CyclicBarrier的Barrier的个数由2改为3,则主线程和子线程会永远等待,因为没有第三个线程执行await方法,即没有第三个线程到达屏障,因此之前到达屏障的两个线程都不会继续执行。

      CyclicBarrier还提供了一个高级的构造器,CyclicBarrier(int parties, Runnable barrierAction),用于在线程到达屏障后,优先执行barrierAction线程里面的逻辑。比如有如下的场景,在所有的线程都处理完成后,打印“All Done”,可以参考如下代码:

      

    public class CyclicBarrierTest2 {
    
        private static CyclicBarrier barrier = new CyclicBarrier(2,new DoneThread());
    
        public static void main(String[] args) throws BrokenBarrierException, InterruptedException {
    
            new Thread(new Runnable() {
    
                @Override
                public void run() {
    
                    System.out.println("thread1");
                    try {
                        barrier.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }
    
            }).start();
    
            System.out.println("mainThread");
            barrier.await();
        }
    
        static class DoneThread implements Runnable{
    
            @Override
            public void run() {
                System.out.println("All Done");
            }
    
        }
    }

      输出结果如下:

    mainThread
    thread1
    All Done

      因此CyclicBarrier常用于处理,多线程计算最后合并计算结果的场景。

    CyclicBarrier和CountDownLatch的区别:

      1.CountDownLatch的计数器只能使用一次,而CyclicBarrier的计数器可以使用reset方法重置,因此CyclicBarrier可以处理线程计算出错时重复计算的场景。

      2.CyclicBarrier还提供了别的有用的方法,如getNumberWaiting可以获得等待的线程数,isBroken方法可以了解阻塞的线程是否被中断等。

  • 相关阅读:
    函数waitpid和WTERMSIG说明(转)
    WIFEXITED WEXITSTATUS WIFSIGNALED(转)
    有关于malloc申请内存和free内存释放
    Using 1-Wire device with Intel Galileo
    Intel Galileo驱动单总线设备(DHT11DHT22)(转)
    360度舵机和180度舵机控制方法小结(转)
    warning: the `gets' function is dangerous and should not be used.(转)
    C语言fgetpos()函数:获得当前文件的读写指针(转)
    关于arduino清空串口缓存(转)
    修改Arduino串口缓冲区大小(转)
  • 原文地址:https://www.cnblogs.com/senlinyang/p/7856184.html
Copyright © 2011-2022 走看看