CyclicBarrier
CyclicBarrier
此类可管理一组线程,当所有线程都到达"检查点"时执行特定的动作(Runnable),示例直接看其源码便好。
类图
和CountDownLatch类似,此类同样没有任何父类(除了Object)或是实现任何接口。
await
整个类的核心便是此方法:
1public int await() {
2 return dowait(false, 0L);
3}
doWait方法简略版源码:
1private int dowait(boolean timed, long nanos) {
2 final ReentrantLock lock = this.lock;
3 lock.lock();
4 try {
5 final Generation g = generation;
6 // 未到达(检查点)数减一
7 int index = --count;
8 // 已达到检查点,执行给定的任务
9 if (index == 0) {
10 boolean ranAction = false;
11 try {
12 final Runnable command = barrierCommand;
13 if (command != null)
14 command.run();
15 ranAction = true;
16 nextGeneration();
17 return 0;
18 } finally {
19 if (!ranAction)
20 breakBarrier();
21 }
22 }
23
24 // 尚有线程未到达检查点
25 for (;;) {
26 try {
27 // 等待
28 if (!timed)
29 trip.await();
30 else if (nanos > 0L)
31 nanos = trip.awaitNanos(nanos);
32 } catch (InterruptedException ie) {
33 if (g == generation && ! g.broken) {
34 breakBarrier();
35 throw ie;
36 } else {
37 Thread.currentThread().interrupt();
38 }
39 }
40
41 if (g.broken)
42 throw new BrokenBarrierException();
43
44 if (g != generation)
45 return index;
46
47 if (timed && nanos <= 0L) {
48 breakBarrier();
49 throw new TimeoutException();
50 }
51 }
52 } finally {
53 lock.unlock();
54 }
55}
一目了然,但是有一个疑问,当未到达数减为0时,已经阻塞的线程是在哪里唤醒的呢?
答案便是nextGeneration方法:
1private void nextGeneration() {
2 // signal completion of last generation
3 trip.signalAll();
4 // set up next generation
5 count = parties;
6 generation = new Generation();
7}