3.13 CountDownLatch
* <p>A {@code CountDownLatch} is initialized with a given <em>count</em>.
* The {@link #await await} methods block until the current count reaches
* zero due to invocations of the {@link #countDown} method, after which
* all waiting threads are released and any subsequent invocations of
* {@link #await await} return immediately.zhe This is a one-shot phenomenon
* -- the count cannot be reset. If you need a version that resets the
* count, consider using a {@link CyclicBarrier}.
通過一個指定數量即可構建CountDownLatch實體,該實體的await方法可以阻塞當前執行緒知道其他執行緒使用該實體的countDown方法使count值減至0,減少至0后所有等待的執行緒都會立即釋放,這是只有一次的操作,因為CountDownLatch的count值只能設定一次,如果一個重新設定count值帶版本號,請使用CyclicBarrier,
3.13.1 CountDownLatch使用方法
1. 通過帶傳入一個count值構造一個CountDownLatch,
CountDownLatch latch = new CountDownLatch(5);
使用await方法可以阻塞當前執行緒,
latch.await();
使用countDown方法可以減少count值,直到該值減至0,所有阻塞的執行緒將立即釋放,
latch.countDown();
完整demo,
public static void main(String[] args) throws InterruptedException {
//創建
CountDownLatch latch = new CountDownLatch(5);
new Thread(()->{
try {
//第一個執行緒被阻塞
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.err.println("其他執行緒等待");
}).start();
for (int i=0;i<10;i++){
Thread.sleep(2000);
new Thread(()->{
//其他執行緒執行countDown(),當count值減少到0,上邊等待的執行緒將被釋放
System.out.println(Thread.currentThread().getName());
latch.countDown();
}).start();
}
}

由上述例子可以看出,通過CountDownLatch可以實作執行緒見通信,完成執行緒執行的先后邏輯,可以實作某執行緒在其他執行緒作業完成后再繼續運行的功能,
3.13.2 CountDownLatch原始碼
其內部由一個Sync組成,其count值Sync這個里面維護著,
private final Sync sync;
再來看看Sync是什么?
/**
* Synchronization control For CountDownLatch.
* Uses AQS state to represent count.
* AbstractQueuedSynchronizer即表示AQS,內部維護了一個正在執行執行緒和等待執行緒之間的關系,
*/
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L;
Sync(int count) {
setState(count);
}
int getCount() {
return getState();
}
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
protected boolean tryReleaseShared(int releases) {
// Decrement count; signal when transition to zero
for (;;) {
int c = getState();
if (c == 0)
return false;
int nextc = c-1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
}
使用CountDownLatch時會先將count值傳入進行構造,該count值再sync里,sync會呼叫setState(count)方法將該值給sync的state屬性,
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
Sync(int count) {
setState(count);
}
呼叫countDown()方法,
public void countDown() {
sync.releaseShared(1);
}
最后countDown()執行的時sync的tryReleaseShared方法邏輯,該releases是1,再getState方法不為0是,會回傳一個回傳一個c-1,就是原來的state減1,
protected boolean tryReleaseShared(int releases) {
// Decrement count; signal when transition to zero
for (;;) {
int c = getState();
if (c == 0)
return false;
int nextc = c-1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/260572.html
標籤:java
上一篇:Java反射機制:跟著代碼學反射
