Java并发编程:CountDownLatch详解与实践

在Java并发编程中,CountDownLatch是一个非常有用的同步工具。它允许一个或多个线程等待一组事件完成。CountDownLatch通过一个计数器实现,计数器的初始值表示需要等待的事件数量。在某个线程完成一个事件后,它会调用countDown()方法,计数器减1。当计数器达到0时,所有等待的线程将被释放,继续执行。
本文将深入分析CountDownLatch的原理、使用方法以及在实际开发中的应用,帮助读者更好地掌握这个并发编程工具。
一、CountDownLatch原理
CountDownLatch基于AQS(AbstractQueuedSynchronizer)抽象同步队列实现。AQS是Java并发编程中的一种基础同步机制,它通过一个共享锁(state)和一系列条件队列(Condition)来实现线程间的同步。
CountDownLatch内部维护一个共享锁(state)和一个条件队列(queue)。初始化时,将共享锁的值设置为计数器的初始值。每当调用countDown()方法时,共享锁的值减1。当共享锁的值减为0时,所有等待的线程将被唤醒。
CountDownLatch的源码如下:
```java
public class CountDownLatch {
private final int count;
private volatile int state = count;
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException();
this.count = count;
}
public void await() throws InterruptedException {
for (; ; ) {
int c = state;
if (c == 0)
return;
if (c > 0) {
Thread.yield();
continue;
}
if (state == c)
continue;
LockSupport.park(this);
}
}
public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
long nanos = unit.toNanos(timeout);
long deadline = System.nanoTime() + nanos;
for (; ; ) {
int c = state;
if (c == 0)
return true;
if (c > 0) {
Thread.yield();
continue;
}
if (state == c)
continue;
long timeLeft = deadline - System.nanoTime();
if (timeLeft <= 0L)
return false;
LockSupport.parkNanos(this, timeLeft);
}
}
public void countDown() {
for (; ; ) {
int c = state;
if (c == 0)
throw new IllegalStateException();
if (c > 0) {
int next = c - 1;
if (next == 0) {
state = 0;
LockSupport.unparkAllWaiters(this);
return;
}
if (next == c)
continue;
state = next;
return;
}
if (state == c)
continue;
LockSupport.unparkAllWaiters(this);
}
}
}
```
二、CountDownLatch使用方法
CountDownLatch的使用非常简单,主要包括以下几个方面:
1. 初始化:创建CountDownLatch对象,并设置计数器的初始值。
```java
CountDownLatch latch = new CountDownLatch(3);
```
2. 等待事件完成:在需要等待事件完成的线程中,调用await()方法。
```java
latch.await();
```
3. 完成事件:在事件完成后,调用countDown()方法。
```java
latch.countDown();
```
4. 异步等待:可以使用await(long timeout, TimeUnit unit)方法实现异步等待,设置超时时间。
```java
boolean isCompleted = latch.await(5, TimeUnit.SECONDS);
```
三、CountDownLatch应用实例
以下是一个使用CountDownLatch实现多线程协作的示例:
```java
public class CountDownLatchExample {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(3);
// 创建并启动三个线程
Thread t1 = new Thread(() -> {
System.out.println("Thread 1 is running...");
latch.countDown();
});
Thread t2 = new Thread(() -> {
System.out.println("Thread 2 is running...");
latch.countDown();
});
Thread t3 = new Thread(() -> {
System.out.println("Thread 3 is running...");
latch.countDown();
});
t1.start();
t2.start();
t3.start();
// 主线程等待三个线程完成
latch.await();
System.out.println("All threads have completed.");
}
}
```
运行上述代码,输出结果如下:
```
Thread 1 is running...
Thread 2 is running...
Thread 3 is running...
All threads have completed.
```
通过CountDownLatch,我们可以轻松实现多线程间的协作,确保线程按照指定的顺序执行。
四、总结
CountDownLatch是Java并发编程中一个非常有用的同步工具。它通过计数器实现线程间的等待与通知,使多线程协作变得简单。在实际开发中,CountDownLatch可以应用于各种场景,如多线程任务分解、线程池管理等。掌握CountDownLatch的使用方法,有助于提高我们的并发编程能力。






