简介
- CountDownLatch是一个同步工具类,用来协调多个线程之间的同步,允许一个或多个线程一直等待,直到其他线程执行完后再执行。
- CountDownLatch是在java1.5被引入的,跟它一起被引入的并发工具类还有CyclicBarrier、Semaphore、ConcurrentHashMap和BlockingQueue,它们都存在于java.util.concurrent包下
- CountDownLatch是通过一个计数器来实现的,计数器的初始化值为线程的数量。
- 每当一个线程完成了自己的任务后,计数器的值就相应得减1。当计数器到达0时,表示所有的线程都已完成任务,然后在闭锁上等待的线程就可以恢复执行任务。
源码
- countDownLatch类中只提供了一个构造器:
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
- 类中最重要的三个方法:
//调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
//与await()类似,等待一定的时间后count值还没变为0的话就会继续执行
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
//对计数器进行递减1操作,当计数器递减至0时,当前线程会去唤醒阻塞队列里的所有线程
public void countDown() {
sync.releaseShared(1);
}
缺陷
- CountDownLatch是一次性的,计数器的值只能在构造方法中初始化一次,之后没有任何机制再次对其设置值,当CountDownLatch使用完毕后,它不能再次被使用。
案例
public class TestDemo {
public static void main(String[] agrs) {
CountDownLatch latch = new CountDownLatch(10);
ExecutorService threadPool1 = new ThreadPoolExecutor(10, 10, 0L, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(), new ThreadPoolExecutor.AbortPolicy());
for (int i = 0; i < 10; i++) {
CountDownLatchRunnable runnable = new CountDownLatchRunnable(latch);
threadPool1.execute(runnable);
}
threadPool1.shutdown();
}
}
class CountDownLatchRunnable implements Runnable {
private CountDownLatch countDownLatch;
public CountDownLatchRunnable(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
try {
synchronized (countDownLatch) {
//每次递减1
countDownLatch.countDown();
System.out.println("------start countDownLatch = " + (countDownLatch.getCount()) + "------");
}
countDownLatch.await();
System.out.println("------end countDownLatch = " + (10 - countDownLatch.getCount()) + "------");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
执行结果: