一,前言
CountDownLatch 是一个非常实用的多线程控制工具类。“Count Down”在英文中意为倒计数, Latch为门闩的意思。简单地称之为倒计数器,这个工具通常用来控制线程等待,它可以让某一个线程等待直到倒计时结束,再开始执行。
CountDownLatch 的构造函数接收一个整数作为参数,即当前这个计数器的计数个数。
public CountDownLatch(int count)
二,构造函数
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
创建一个参数为 count 的 Sync 对象,看看 Sync 代码:
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;
}
}
}
可以看到,Sync(int count) 构造函数中,默认加上了 count 把锁!
三,源码
await()
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
可见,底层使用了 AQS 的 acquireSharedInterruptibly 方法 进行获取共享锁!由于创建 CountDownLatch 对象时已经加上了 count 把锁,通过 await() 方法阻塞在等待队列尾部。等待 state = 0 锁释放完,再去获取锁。
countDown()
public void countDown() {
sync.releaseShared(1);
}
可见,底层使用了 AQS 的 releaseShared 方法释放一把共享锁。
四,简单使用
import java.util.concurrent.*;
public class CountDownLatchDemo implements Runnable {
private static final CountDownLatch latch = new CountDownLatch(10);
private static final CountDownLatchDemo demo = new CountDownLatchDemo();
public static void main(String[] args) throws InterruptedException {
ExecutorService exec = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
Thread.sleep(100);
// 执行子线程 计数-1
exec.submit(demo);
}
// 等待检查
latch.await();
// 倒计时结束后再继续执行
System.out.println("go on..." + ":线程:" + Thread.currentThread().getName());
// 关闭线程池
exec.shutdown();
}
@Override
public void run() {
System.out.println("checking...倒计时:" + latch.getCount() + ":线程:" + Thread.currentThread().getName());
// 计数-1
latch.countDown();
}
}
执行结果:
checking...倒计时:10:线程:pool-1-thread-1
checking...倒计时:9:线程:pool-1-thread-2
checking...倒计时:8:线程:pool-1-thread-3
checking...倒计时:7:线程:pool-1-thread-4
checking...倒计时:6:线程:pool-1-thread-5
checking...倒计时:5:线程:pool-1-thread-6
checking...倒计时:4:线程:pool-1-thread-7
checking...倒计时:3:线程:pool-1-thread-8
checking...倒计时:2:线程:pool-1-thread-9
checking...倒计时:1:线程:pool-1-thread-10
go on...:线程:main
评论区