CountDownLatch 是 Java.util.concurrent 包中提供的一个同步工具类,用于控制线程的执行顺序。它通过一个计数器来实现,计数器的初始值可以设置,并且当计数器的值减到零时,所有等待线程将被释放。
1. 这是一个使用 CountDownLatch 的示例代码,演示了如何等待多个工作线程完成任务。
import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
public static void main(String[] args) throws InterruptedException {
int workerCount = 5;
CountDownLatch countDownLatch = new CountDownLatch(workerCount);
for (int i = 0; i < workerCount; i++) {
Thread worker = new Thread(new Worker(countDownLatch));
worker.start();
}
countDownLatch.await(); // 主线程等待所有工作线程完成
System.out.println("All workers have completed their tasks.");
}
static class Worker implements Runnable {
private final CountDownLatch countDownLatch;
public Worker(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
try {
// 模拟工作任务的执行
Thread.sleep(1000);
System.out.println("Worker " + Thread.currentThread().getId() + " has completed the task.");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
countDownLatch.countDown(); // 完成任务后计数器减1
}
}
}
}
在这个示例中,我们创建了一个 CountDownLatch
对象,初始计数器的值为 5,表示有 5 个工作线程需要执行完毕。
在 for
循环中,我们创建了 5 个工作线程,每个工作线程执行一个模拟的工作任务。在任务执行完毕后,调用 countDownLatch.countDown()
方法,将计数器减一。
在主线程中,调用 countDownLatch.await()
方法,使主线程等待,直到计数器减为 0。一旦计数器减为 0,表示所有工作线程都执行完毕,主线程会继续执行后续操作。
输出结果可能类似于以下内容:
Worker 9 has completed the task.
Worker 10 has completed the task.
Worker 8 has completed the task.
Worker 11 has completed the task.
Worker 12 has completed the task.
All workers have completed their tasks.
这个示例展示了如何使用 CountDownLatch 来等待多个工作线程执行完毕,并在所有线程完成后继续执行后续操作。
2. 这是一个使用 CountDownLatch 的示例代码,模拟班级上完自习后班长锁门离开教室的场景。
import java.util.concurrent.CountDownLatch;
public class CountDownLatchDemo {
public static void main(String[] args) throws Exception {
closeDoor();
}
/**
* 关门案例
*
* @throws InterruptedException
*/
private static void closeDoor() throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 1; i <= 6; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t" + "上完自习");
countDownLatch.countDown();
}, String.valueOf(i)).start();
}
countDownLatch.await();
System.out.println(Thread.currentThread().getName() + "\t班长锁门离开教室");
}
}
在这个示例中,我们创建了一个 CountDownLatch
对象,初始计数器的值为 6,表示有 6 个线程需要执行完毕。
在 for
循环中,我们创建了 6 个线程,每个线程表示一个学生上完自习。每个线程执行完上完自习的操作后,调用 countDownLatch.countDown()
方法,将计数器减一。
在主线程中,调用 countDownLatch.await()
方法,使主线程等待,直到计数器减为 0。一旦计数器减为 0,表示所有线程都执行完毕,主线程会继续执行后续操作,即班长锁门离开教室的动作。
输出结果可能类似于以下内容:
1 上完自习
2 上完自习
3 上完自习
4 上完自习
5 上完自习
6 上完自习
班长锁门离开教室
这个示例展示了如何使用 CountDownLatch 来等待一组线程执行完毕,并在所有线程完成后继续执行后续操作。
CountDownLatch 底层原理涉及到线程同步和共享变量的操作
CountDownLatch 的底层原理是基于 AQS(AbstractQueuedSynchronizer)实现的。具体来说, CountDownLatch 内部维护了一个共享的同步状态(state),每个线程执行 countDown()
方法时,会让 state 减 1 。而主线程调用 await()
方法时,会阻塞自己,直到 state 减到零才恢复执行。这样就实现了线程之间的协调与等待的功能,主线程等待所有工作线程完成后再继续执行。
在 CountDownLatch 中,有一个计数器(count)用于表示需要等待的事件数量。计数器的初始值由构造函数传入,每当一个事件完成时,计数器的值会减一。当计数器的值变为零时,表示所有事件都已完成,等待的线程可以继续执行。
CountDownLatch 使用了共享变量和内置的线程同步机制来实现等待和通知的功能。具体来说,它使用了以下几个关键的方法:
countDown()
:每当一个事件完成时,调用countDown()
方法将计数器的值减一。await()
:等待的线程调用await()
方法,如果计数器的值不为零,则线程会被阻塞,直到计数器的值变为零。- 内置的同步机制:CountDownLatch 内部使用了内置的同步机制,如锁、条件变量等,来实现线程的等待和通知机制。
当一个线程调用 countDown()
方法时,它会尝试获取内置的锁,然后将计数器的值减一。如果计数器的值变为零,那么所有在 await()
方法中等待的线程将会被唤醒,可以继续执行。
需要注意的是,CountDownLatch 是一次性的,一旦计数器的值变为零,就无法重置。如果需要重复使用类似的功能,可以考虑使用 CyclicBarrier 或 Phaser 等其他的线程同步工具。
总结起来,CountDownLatch 的底层原理是通过共享变量和内置的线程同步机制来实现等待和通知的功能。它提供了简单而有效的方式来等待多个事件的完成。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。