倒计数器CountDownLatch
CountDownLatch介绍
CountDownLatch是Java并发编程中一个非常实用的同步工具类,它位于java.util.concurrent
包下,是JDK 1.5以后加入的。CountDownLatch通过一个计数器来控制多个线程的执行顺序,允许一个或多个线程等待其他线程完成操作后再继续执行。
CountDownLatch的主要方法
-
构造函数:
CountDownLatch(int count)
,传入一个参数count
,表示计数器的初始值。 -
await():调用该方法的线程会阻塞,直到计数器值减至0。
-
await(long timeout, TimeUnit unit):与
await()
方法类似,但增加了超时时间,如果超时则不再等待。 -
countDown():将计数器的值减1,如果计数器的值变为0,则唤醒所有因调用
await()
方法而阻塞的线程。
经典应用场景
-
应用启动时的初始化
在应用程序启动时,可能需要等待多个初始化任务完成(如数据库连接、配置加载等)后,才允许处理客户端请求。此时,可以使用CountDownLatch来等待所有初始化任务完成。
-
并行任务的同步
当一个任务需要等待多个并行执行的任务全部完成才能继续时,可以使用CountDownLatch。例如,在并行计算中,将大任务拆分成多个子任务,等待所有子任务完成后,再进行汇总处理。
-
测试高并发场景
在模拟高并发测试时,可以控制多个线程同时开始执行,以测试系统在高负载下的表现。通过CountDownLatch,可以确保所有线程同时开始执行。
具体代码示例
使用CountDownLatch的示例,展示了如何让主线程等待若干个子线程全部完成后再继续执行:
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CountDownLatchDemo {
public static int threadCount = 5;
public static ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
public static CountDownLatch latch = new CountDownLatch(threadCount);
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < threadCount; ++i) {
executorService.execute(new WorkerThread());
}
latch.await(); // 主线程在此等待,直到计数器变为0
System.out.println("所有子线程执行完成,主线程继续执行");
executorService.shutdown();
}
static class WorkerThread implements Runnable {
@Override
public void run() {
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + " 完成任务");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
latch.countDown(); //完成任务后计数减1
}
}
}
}
在这个例子中,我们创建了一个固定大小的线程池来执行5个WorkerThread
任务。每个工作线程完成自己的任务后会调用latch.countDown()
减少计数器的值。主线程则通过调用latch.await()
等待,直到所有的工作线程都完成了它们的任务(即计数器变为0),之后主线程才会继续执行。相对于join(),CountDownLatch使用起来非常方便。
稍微修改一下上面的示例,就得到以下控制多个线程同时开始执行例子:
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CountDownLatchDemo {
public static int threadCount = 5;
public static ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
public static CountDownLatch latch = new CountDownLatch(1);
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < threadCount; ++i) {
executorService.execute(new WorkerThread());
}
Thread.sleep(3000);
latch.countDown();
executorService.shutdown();
}
static class WorkerThread implements Runnable {
@Override
public void run() {
try {
latch.await();
System.out.println(Thread.currentThread().getName() + " 开始执行");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
上述示例中将计数器CountDownLatch初始化为1,所有线程都阻塞在await()上,主线程等待3秒后调用countDown()将计数器减为0,于是所有子线程都同时被唤醒,并开始执行,这样就可以模拟多个线程同时并发执行的情况。
参考
CountDownLatch的 常用场景及使用示例_countdownlatch应用场景-CSDN博客
原文地址:https://blog.csdn.net/qq_38875964/article/details/142552771
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!