- CountDownLatch本质其实就是一个计数器。
- 在多线程并形处理业务时,需要等待其他线程处理完,再做后续的合并等操作,再响应用户时,可以使用CountDownLatch做计数,等到其他线程出现完之后,主线程就会被唤醒。
- CountDownLatch本身就是基于AQS实现的。
- new CountDownLatch时,直接指定好具体的数值。这个数值会复制给state属性。
- 当子线程处理完任务后,执行countDown方法,内部就是直接给state - 1而已。
- 当state减为0之后,执行await挂起的线程,就会被唤醒。
- CountDownLatch不能重复使用
实现原理、应用场景
CountDownLatch的底层实现通常依赖于对底层的同步器(synchronizer)的使用,最常见的同步器是基于AQS(AbstractQueuedSynchronizer)的实现。
在AQS中,CountDownLatch使用一个共享的同步状态来表示等待的线程数。每个等待线程都调用await()方法来阻塞自己,直到计数器减为0。当一个线程调用countDown()方法时,计数器减一。一旦计数器达到零,所有被阻塞的线程将被同时释放,允许它们继续执行。
CountDownLatch的主要适用场景是在一个或多个线程等待其他线程完成某个操作,然后再继续执行的情况下。一些常见的应用场景包括:
- 主线程等待多个工作线程完成:当主线程需要等待多个工作线程完成某个任务后才能继续执行时,可以使用CountDownLatch。主线程可以调用await()方法来等待所有工作线程完成,并在所有工作线程调用countDown()方法后继续执行。
- 并发任务的协调:在并发编程中,当多个任务需要等待其他任务完成某个操作后再继续执行时,可以使用CountDownLatch来进行协调。每个任务可以在执行完自己的操作后调用countDown()方法,等待其他任务的任务可以在调用await()方法后阻塞自己,直到所有的任务都完成。
- 测试并发性能:在进行并发性能测试时,可以使用CountDownLatch来协调并发任务的开始和结束。测试线程可以在开始时调用await()方法等待所有任务准备就绪,然后同时释放所有任务开始执行。测试线程还可以在结束时调用await()方法等待所有任务执行完毕,然后进行性能统计和结果分析。
总的来说,CountDownLatch是一种用于多个线程之间进行协调和同步的工具,适用于一些需要等待其他线程完成某个操作后才能继续执行的场景。它能够有效地控制线程的执行顺序和并发性,提供了一种简单而灵活的线程间通信方式。
代码示例
下面是一个使用CountDownLatch的代码示例,展示了如何在多个线程之间进行同步等待:
import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
public static void main(String[] args) throws InterruptedException {
int threadsCount = 3;
CountDownLatch latch = new CountDownLatch(threadsCount);
for (int i = 0; i < threadsCount; i++) {
Thread thread = new Thread(new Worker(latch));
thread.start();
}
System.out.println("等待所有线程完成...");
latch.await(); // 主线程等待所有工作线程完成
System.out.println("所有线程已完成");
}
static class Worker implements Runnable {
private final CountDownLatch latch;
public Worker(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void run() {
// 模拟工作
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 完成工作");
// 完成工作,倒计时减一
latch.countDown();
}
}
}
在上述示例中,我们创建了一个CountDownLatch对象并初始化为3(threadsCount)。然后,我们创建了3个工作线程(Worker),每个线程在完成工作后调用CountDownLatch的countDown()方法将倒计时减一。
主线程调用CountDownLatch的await()方法来等待所有工作线程完成。在所有工作线程都调用了countDown()方法之后,倒计时减为0,await()方法返回,主线程继续执行后续操作。
输出示例:
等待所有线程完成...
Thread-0 完成工作
Thread-1 完成工作
Thread-2 完成工作
所有线程已完成
通过CountDownLatch,我们可以实现多个线程之间的同步等待,主线程可以在所有工作线程完成后继续执行。这对于协调多个线程的并发任务非常有用。