1. CountDownLatch的基本应用
- CountDownLatch本身就好像一个计数器,可以让一个线程或多个线程等待其他线程完成后再执行
应用方式
public static void main(String[] args) throws InterruptedException, BrokenBarrierException {
// 声明CountDownLatch,有参构造传入的值,会赋值给state,CountDownLatch基于AQS实现
CountDownLatch countDownLatch = new CountDownLatch(3);
new Thread(() -> {
System.out.println("111");
// state -1
countDownLatch.countDown();
}).start();
new Thread(() -> {
System.out.println("222");
// state -1
countDownLatch.countDown();
}).start();
new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("333");
// state -1
countDownLatch.countDown();
}).start();
// 主线会阻塞在这个位置,直到CountDownLatch的state变为0
countDownLatch.await();
System.out.println("main");
}
2. CountDownLatch核心源码分析
2.1 从构造方法查看
// CountDownLatch 的有参构造
public CountDownLatch(int count) {
// 健壮性校验
if (count < 0) throw new IllegalArgumentException("count < 0");
// 构建Sync给AQS的state赋值
this.sync = new Sync(count);
}
2.2 countDown方法
// countDown方法,本质就是调用了AQS的释放共享锁操作
// 这里的功能都是AQS提供的,只有tryReleaseShared需要实现的类自己去编写业务
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
// 唤醒在AQS队列中排队的线程。
doReleaseShared();
return true;
}
return false;
}
// countDownLatch实现的业务
protected boolean tryReleaseShared(int releases) {
for (;;) {
int c = getState();
if (c == 0)
return false;
// state - 1
int nextc = c-1;
// 用CAS赋值
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
// 如果CountDownLatch中的state已经为0了,那么再次执行countDown跟没执行一样。
// 而且只要state变为0,await就不会阻塞线程。
2.3 await方法
// await方法
public void await() throws InterruptedException {
// 调用了AQS提供的获取共享锁并且允许中断的方法
sync.acquireSharedInterruptibly(1);
}
// AQS提欧的获取共享锁并且允许中断的方法
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
// countDownLatch操作
if (tryAcquireShared(arg) < 0)
// 如果返回的是-1,代表state肯定大于0
doAcquireSharedInterruptibly(arg);
}
// CountDownLatch实现的tryAcquireShared
protected int tryAcquireShared(int acquires) {
// state为0,返回1,。否则返回-1
return (getState() == 0) ? 1 : -1;
}
// 让当前线程进到AQS队列,排队去
private void doAcquireSharedInterruptibly(int arg) throws InterruptedException {
// 将当前线程封装为Node,并且添加到AQS的队列中
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head) {
// 再次走上面的tryAcquireShared,如果返回的是的1,代表state为0
int r = tryAcquireShared(arg);
if (r >= 0) {
// 会将当前线程和后面所有排队的线程都唤醒。
setHeadAndPropagate(node, r);
p.next = null; // help GC
failed = false;
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}