zoukankan      html  css  js  c++  java
  • 源码阅读

    CyclicBarrier是一个用于线程同步的辅助类,它允许一组线程等待彼此,直到所有线程都到达集合点,然后执行某个设定的任务。

    举个例子:几个人约定了某个地方集中,然后一起出发去旅行。每个参与的人就是一个线程,CyclicBarrier就是那个集合点,所有人到了之后,就一起出发。

    CyclicBarrier的构造函数有两个:

    1 // parties是参与等待的线程的数量,barrierAction是所有线程达到集合点之后要做的动作
    2 public CyclicBarrier(int parties, Runnable barrierAction);
    3 
    4 // 达到集合点之后不执行操作的构造函数
    5 public CyclicBarrier(int parties)

     CyclicBarrier只是记录线程的数目,CyclicBarrier是不创建任何线程的。线程是通过调用CyclicBarrier的await方法来等待其他线程,如果调用await方法的线程数目达到了预设值,也就是上面构造方法中的parties,CyclicBarrier就会开始执行barrierAction。

    因此我们来看CyclicBarrier的核心方法dowait,也就是await方法调用的私有方法:

     1 private int dowait(boolean timed, long nanos)
     2         throws InterruptedException, BrokenBarrierException,
     3                TimeoutException {
     4         final ReentrantLock lock = this.lock;
     5         lock.lock();
     6         try {
     7             final Generation g = generation;
     8 
     9             if (g.broken)
    10                 throw new BrokenBarrierException();
    11 
    12             if (Thread.interrupted()) {
    13                 breakBarrier();
    14                 throw new InterruptedException();
    15             }
    16            // count就是预设的parties,count减1的值表示还剩余几个
    17            // 线程没有达到该集合点
    18            int index = --count;
    19            // index为0表示所有的线程都已经达到集合点,这时
    20            // 占用最后一个线程,执行运行设定的任务
    21            if (index == 0) {
    22                boolean ranAction = false;
    23                try {
    24                    final Runnable command = barrierCommand;
    25                    if (command != null)
    26                        command.run();
    27                    ranAction = true;
    28                    // 唤醒其他等待的线程,
    29                    // 更新generation以便下一次运行
    30                    nextGeneration();
    31                    return 0;
    32                } finally {
    33                    // 如果运行任务时发生异常,设置状态为broken
    34                    // 并且唤醒其他等待的线程
    35                    if (!ranAction)
    36                        breakBarrier();
    37                }
    38            }
    39 
    40             // 还有线程没有调用await,进入循环等待直到其他线程
    41             // 达到集合点或者等待超时
    42             for (;;) {
    43                 try {
    44                     // 如果没有设置超时,进行无超时的等待
    45                     if (!timed)
    46                         trip.await();
    47                     // 有超时设置,进行有超时的等待
    48                     else if (nanos > 0L)
    49                         nanos = trip.awaitNanos(nanos);
    50                 } catch (InterruptedException ie) {
    51                     // generation如果没有被更新表示还是当前的运行
    52                     // (generation被更新表示集合完毕并且任务成功),
    53                     // 在状态没有被设置为broken状态的情况下,遇到线程
    54                     // 中断异常表示当前线程等待失败,需要设置为broken
    55                     // 状态,并且抛出中断异常
    56                     if (g == generation && ! g.broken) {
    57                         breakBarrier();
    58                         throw ie;
    59                     } else {
    60                         // else对应的条件为:g != generation || g.broken
    61                         // 表示要么generation已经被更新意味着所有线程已经到达
    62                         // 集合点并且任务执行成功,要么就是是broken状态意味着
    63                         // 任务执行失败,无论哪种情况所有线程已经达到集合点,当
    64                         // 前线程要结束等待了,发生了中断异常,需要中断当前线程
    65                         // 表示遇到了中断异常。
    66                         Thread.currentThread().interrupt();
    67                     }
    68                 }
    69 
    70                 // 如果发现当前状态为broken,抛出异常
    71                 if (g.broken)
    72                     throw new BrokenBarrierException();
    73                 // generation被更新表示所有线程都已经达到集合点
    74                 // 并且预设任务已经完成,返回该线程进入等待顺序号
    75                 if (g != generation)
    76                     return index;
    77                 // 等待超时,设置为broken状态并且抛出超时异常
    78                 if (timed && nanos <= 0L) {
    79                     breakBarrier();
    80                     throw new TimeoutException();
    81                 }
    82             }
    83         } finally {
    84             lock.unlock();
    85         }
    86     }

    1. 任何一个线程等待时发生异常,CyclicBarrier都将被设置为broken状态,运行都会失败

    2. 每次运行成功之后CyclicBarrier都会清理运行状态,这样CyclicBarrier可以重新使用

    3. 对于设置了超时的等待,在发生超时的时候会引起CyclicBarrier的broken

  • 相关阅读:
    75. Sort Colors
    101. Symmetric Tree
    121. Best Time to Buy and Sell Stock
    136. Single Number
    104. Maximum Depth of Binary Tree
    70. Climbing Stairs
    64. Minimum Path Sum
    62. Unique Paths
    css知识点3
    css知识点2
  • 原文地址:https://www.cnblogs.com/zcjcsl/p/8429118.html
Copyright © 2011-2022 走看看