java.lang.Concurrent包下的可阻塞类CountDownLatch(倒数计数器),基于基类AQS(AbstractQueuedSynchronizer)标准队列同步器类。在同步状态state中保存的是当前的计数值。countDown()调用release,从而导致计数器值递减,并且计数器值为零时,解除所有等待线程的阻塞。await()调用accquie,当计数器值为零时,acquire将立即返回,否则将阻塞。
await():阻塞当前线程,将当前线程加入AQS的阻塞队列;
countDown():对计数器进行递减操作,当计数器递减至0时,当前线程会取唤醒阻塞队列中的所有线程。
package com.example.demo.concurrent;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CountDownLatchDemo implements Runnable{
final static CountDownLatchDemo demo =new CountDownLatchDemo();
//创建一个AQS的同步队列,并把初始化的计数器值5赋值给AQS队列的state
final static CountDownLatch latch=new CountDownLatch(5);
@Override
public void run() {
try {
Thread.sleep(100);
System.out.println("finish one task");
//通知CountDownLatch有一个线程已经完成了任务,计数器减1
//AQS内部是通过release释放锁的方式,对state进行减1操作,当state=0时,说明计数器已递减完毕,此时会将AQS阻塞队列里的节点线程全部唤醒。
latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ExecutorService pools = Executors.newFixedThreadPool(5);
for (int i=0;i<5;i++){
pools.execute(demo);
}
try {
//创建一个节点,加入到AQS阻塞队列,并把当前线程挂起;
//要求主线程等待所有检查任务全部完成,当第5个任务全部完成后,主线程才能被唤醒,继续执行;
latch.await();
System.out.println("finish All");
} catch (InterruptedException e) {
e.printStackTrace();
}
pools.shutdown();
}
}
输出结果:
finish one task
finish one task
finish one task
finish one task
finish one task
finish All