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

  • 相关阅读:
    MySQL中IS NULL、IS NOT NULL、!=不能用索引?胡扯!
    市值TOP10,人类进化及中美坐标
    倒序切片
    对list进行切片
    Python之定义可变参数
    Python之递归函数
    Python之“可变”的tuple
    Python之创建单元素tuple
    Python中Unicode字符串
    Pycharm配置autopep8让Python代码更符合pep8规范
  • 原文地址:https://www.cnblogs.com/zcjcsl/p/8429118.html
Copyright © 2011-2022 走看看