一、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/zh-hant/n/298213.html
微信掃一掃
支付寶掃一掃