一、CountDownLatch概述
CountDownLatch是Java并发包中提供的一种同步工具类,它可以让一个或多个线程等待其他线程的完成。CountDownLatch内部维护了一个计数器,这个计数器可以被任意线程减少,并且只能被减少一次,一旦计数器为0,等待的线程就可以继续执行下去。
CountDownLatch的构造函数需要一个参数count,表示需要等待的线程数量,也就是计数器的初始值。当需要等待的线程都完成了任务后,调用CountDownLatch的countdown()方法,将计数器的值减1。使用await()方法的线程会阻塞,直到计数器为0,才能继续执行下去。
import java.util.concurrent.CountDownLatch;
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
int nThreads = 5;
CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch endSignal = new CountDownLatch(nThreads);
for (int i = 0; i < nThreads; i++) {
Thread thread = new Thread(new Task(startSignal, endSignal), "Thread-"+i);
thread.start();
}
System.out.println("主线程等待子线程执行任务...");
startSignal.countDown();
endSignal.await();
System.out.println("所有子线程执行任务完毕,继续执行其他任务...");
}
private static class Task implements Runnable {
private final CountDownLatch startSignal;
private final CountDownLatch endSignal;
public Task(CountDownLatch startSignal, CountDownLatch endSignal) {
this.startSignal = startSignal;
this.endSignal = endSignal;
}
@Override
public void run() {
try {
startSignal.await();
System.out.println(Thread.currentThread().getName() + " 正在执行任务...");
Thread.sleep((long) (Math.random() * 5000));
System.out.println(Thread.currentThread().getName() + " 任务执行完毕.");
endSignal.countDown();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
二、使用CountDownLatch实现并发控制
CountDownLatch可以很方便地用于实现并发控制,可以控制多个线程在特定的时刻同时开始或同时结束执行。
下面的代码演示了如何使用CountDownLatch实现多个线程在特定时间点同时开始执行。
import java.util.concurrent.CountDownLatch;
public class ConcurrentControlDemo {
public static void main(String[] args) throws InterruptedException {
int concurrentNum = 3;
final CountDownLatch startSignal = new CountDownLatch(1);
final CountDownLatch endSignal = new CountDownLatch(concurrentNum);
for (int i = 0; i < concurrentNum; i++) {
Thread thread = new Thread(new Task(startSignal, endSignal), "Thread-"+i);
thread.start();
}
System.out.println("主线程正在做其他事情...");
Thread.sleep(5000);
System.out.println("主线程做完了,允许并发程序开始执行任务...");
startSignal.countDown();
endSignal.await();
System.out.println("所有子线程执行任务完毕,继续执行其他任务...");
}
private static class Task implements Runnable {
private final CountDownLatch startSignal;
private final CountDownLatch endSignal;
public Task(CountDownLatch startSignal, CountDownLatch endSignal) {
this.startSignal = startSignal;
this.endSignal = endSignal;
}
@Override
public void run() {
try {
startSignal.await();
System.out.println(Thread.currentThread().getName() + " 正在执行任务...");
Thread.sleep((long) (Math.random() * 5000));
System.out.println(Thread.currentThread().getName() + " 任务执行完毕.");
endSignal.countDown();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
三、CountDownLatch的特点和使用场景
CountDownLatch的特点:
- 对计数器的操作是原子操作,多个线程可以安全地操作同一个CountDownLatch对象。
- 一旦计数器的值变为0,就不能再被增加。
- 一旦计数器的值变为0,await()方法会立刻返回,不会阻塞。
- CountDownLatch不能重用,如果需要重用,需要创建新的实例。
CountDownLatch的使用场景:
- 控制多个线程在特定的时刻同时开始或同时结束执行。
- 等待一组并行执行的任务完成后再继续执行下一步操作。
- 可以用于测试多线程代码的正确性,确保多个线程在特定的时刻达到预期的状态。
四、小结
CountDownLatch是一个非常有用的并发工具类,可以控制多个线程在特定的时刻同时开始或同时结束执行。使用CountDownLatch可以很方便地实现对并发执行的控制,提高程序的效率。
原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/298213.html
微信扫一扫
支付宝扫一扫