源码阅读 - java.util.concurrent (四)CyclicBarrier

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

 

posted @ 2018-03-22 00:09  强迫疒  阅读(169)  评论(0编辑  收藏  举报