一、介绍
CountDownLatch
是一个并发工具类,它的作用是可以完成线程的协作,通常的场景是 主线程等待 多个子线程执行完成后再处理,类似于Jion
功能。
二、使用方法
public static void main(String[] args) throws Exception {
// 设置挡板数量
final CountDownLatch latch = new CountDownLatch(10);
for (int i = 0; i <= 9; i++) {
final int num = i;
new Thread(()->{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
log.info("this thread id is {} and i is {} ",Thread.currentThread().getName(),num);
latch.countDown();
}
}).start();
}
latch.await();
log.info("fish and latch count is {}",latch.getCount());
}
三、源码分析
- 初始化
CountDownLatch
,其内部也是依拖于AQS框架实现的
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
// 创建同步处理器
this.sync = new Sync(count);
}
// 继承自AbstractQueuedSynchronizer
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;
}
}
}
- 关键方法:获取资源
tryAcquireShared
如果当前count == 0 返回1,否则返回-1 (这个判断很关键,后面会讲到)
3.1 为什么await()
方法能够等待
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
它调用的是同步器的共享锁获取,看一下具体的实现:
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
//
if (tryAcquireShared(arg) < 0)
// 进入队列,自旋等待
doAcquireSharedInterruptibly(arg);
}
可以看到代码,如果tryAcquireShared
小于0 ,那么该线程就进入自旋等待。也就符合上的逻辑,当count >0时 返回 -1.。那么就能够猜测到,当执行countDown方法时,就是使 stateCount 状态 -1.
3.2 CountDown()方法
//
public void countDown() {
sync.releaseShared(1);
}
protected boolean tryReleaseShared(int releases) {
// Decrement count; signal when transition to zero
for (;;) {
int c = getState();
if (c == 0)
return false;
// 状态Count - 1;
int nextc = c-1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
3.3 小结
CountDownLathch
的实现原理依托于AQS
,设置的挡板数量Count
,就是AQS的共享状态资源。主任务线程await()
时,判断count是否 == 0, 否则会进入等待队列,自旋。
4 参考
《并发编程的艺术》