1. 類的定義
public class CyclicBarrier
複製程式碼
2. 欄位屬性
//獨佔鎖
private final ReentrantLock lock = new ReentrantLock();
//等待的條件
private final Condition trip = lock.newCondition();
//執行緒等待的數量,重置count
private final int parties;
//被喚醒時,優先執行的任務
private final Runnable barrierCommand;
//描述更新換代,重置?
//Generation中的broken表示這一次是否完成,預設false。count為0時設定為true
private Generation generation = new Generation();
//記錄當前需要等待到來的執行緒數,等於0表示到下一代,通過parties來重置
private int count;
複製程式碼
從欄位屬性可以看出
- CyclicBarrier使用ReentrantLock來達到同步功能
- 所有的執行緒等待Condition喚醒,即count為0的時候喚醒所有執行緒
- CyclicBarrier的重置功能使用Generation和parties來完成
- CyclicBarrier可以使用barrierCommand處理一部份邏輯
3. 構造方法
//傳入執行緒數量
public CyclicBarrier(int parties) {
//呼叫下面的構造方法
this(parties, null);
}
//傳入執行緒數量和要處理的業務
public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) throw new IllegalArgumentException();
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;
}
複製程式碼
從構造方法可以看出
- count使用parties初始化
- barrierCommand可以為null
4. 方法
nextGeneration 方法
//設定為新生代,喚醒執行緒並重置狀態
private void nextGeneration() {
//喚醒所有等待condition的執行緒
trip.signalAll();
//重置count
count = parties;
//重置generation,新生代
generation = new Generation();
}
複製程式碼
breakBarrier 方法
//設定當前代為完成狀態
private void breakBarrier() {
//設定當前代為完成狀態
generation.broken = true;
//重置count
count = parties;
//喚醒所有等待condition的執行緒
trip.signalAll();
}
複製程式碼
dowait 方法
private int dowait(boolean timed, long nanos)
throws InterruptedException, BrokenBarrierException,
TimeoutException {
//加鎖
final ReentrantLock lock = this.lock;
lock.lock();
try {
//獲取當前代
final Generation g = generation;
if (g.broken)
//如果當前代已經處於完成狀態,丟擲異常
throw new BrokenBarrierException();
if (Thread.interrupted()) {
//如果當前執行緒已經被中斷
//設定當前代為完成狀態
breakBarrier();
//丟擲異常
throw new InterruptedException();
}
//count減1
int index = --count;
if (index == 0) { // tripped
//如果count為0,表示所有執行緒已經就緒
boolean ranAction = false;
try {
//先執行優先執行的任務
final Runnable command = barrierCommand;
if (command != null)
command.run();
ranAction = true;
//設定為新生代,喚醒執行緒並重置狀態
nextGeneration();
return 0;
} finally {
if (!ranAction)
//執行優先執行的任務丟擲異常的情況
//設定當前代為完成狀態
breakBarrier();
}
}
// loop until tripped, broken, interrupted, or timed out
for (;;) {
try {
if (!timed)
//未設定超時
//直接進入條件等待
trip.await();
else if (nanos > 0L)
//設定超時,進入有超時時間的條件等待
nanos = trip.awaitNanos(nanos);
} catch (InterruptedException ie) {
//丟擲異常
if (g == generation && ! g.broken) {
//當前代不變且為完成
//設定當前代為完成狀態
breakBarrier();
throw ie;
} else {
//當前代已經改變,中斷當前執行緒
Thread.currentThread().interrupt();
}
}
if (g.broken)
throw new BrokenBarrierException();
if (g != generation)
return index;
if (timed && nanos <= 0L) {
//超時
//設定當前代為完成狀態
breakBarrier();
throw new TimeoutException();
}
}
} finally {
//釋放鎖資源
lock.unlock();
}
}
複製程式碼
getParties 方法
//獲取設定等待的執行緒數
public int getParties() {
return parties;
}
複製程式碼
await 方法
//進入條件等待
public int await() throws InterruptedException, BrokenBarrierException {
try {
//呼叫dowait方法
return dowait(false, 0L);
} catch (TimeoutException toe) {
throw new Error(toe); // cannot happen
}
}
//進入有超時時間的條件等待
public int await(long timeout, TimeUnit unit)
throws InterruptedException,
BrokenBarrierException,
TimeoutException {
//呼叫dowait方法
return dowait(true, unit.toNanos(timeout));
}
複製程式碼
isBroken 方法
//獲取當前代狀態
public boolean isBroken() {
//上鎖
final ReentrantLock lock = this.lock;
lock.lock();
try {
//返回當前代狀態
return generation.broken;
} finally {
//釋放鎖資源
lock.unlock();
}
}
複製程式碼
reset 方法
//重置當前代狀態
public void reset() {
//上鎖
final ReentrantLock lock = this.lock;
lock.lock();
try {
//設定當前代為完成狀態
breakBarrier(); // break the current generation
//設定為新生代代,喚醒執行緒並重置狀態
nextGeneration(); // start a new generation
} finally {
//釋放鎖
lock.unlock();
}
}
複製程式碼
getNumberWaiting 方法
//獲取等待中的執行緒數
public int getNumberWaiting() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
//parties 需要的執行緒總數
//count 還需要等待到來的執行緒數
return parties - count;
} finally {
lock.unlock();
}
}
複製程式碼