1.JAVA多線程(十二)Java多線程之CountDownLatch
1.1 CountDownLatch是什麼?
CountDownLatch 是一個同步工具類,它允許一個或多個線程一直等待,直到其他線程的操作執行完後再執行。CountDownLatch是在java1.5被引入的,跟它一起被引入的併發工具類還有CyclicBarrier、Semaphore、ConcurrentHashMap和BlockingQueue,它們都存在於java.util.concurrent包下。CountDownLatch這個類能夠使一個線程等待其他線程完成各自的工作後再執行。例如,應用程序的主線程希望在負責啓動框架服務的線程已經啓動所有的框架服務之後再執行。
-
某一線程在開始運行前等待 n 個線程執行完畢。將 CountDownLatch 的計數器初始化爲 n :new CountDownLatch(n),每當一個任務線程執行完畢,就將計數器減 1 countdownlatch.countDown(),當計數器的值變爲 0 時,在CountDownLatch上 await() 的線程就會被喚醒。一個典型應用場景就是啓動一個服務時,主線程需要等待多個組件加載完畢,之後再繼續執行。
-
實現多個線程開始執行任務的最大並行性。注意是並行性,不是併發,強調的是多個線程在某一時刻同時開始執行。類似於賽跑,將多個線程放到起點,等待發令槍響,然後同時開跑。做法是初始化一個共享的 CountDownLatch 對象,將其計數器初始化爲 1 :new CountDownLatch(1),多個線程在開始執行任務前首先 coundownlatch.await(),當主線程調用 countDown() 時,計數器變爲 0,多個線程同時被喚醒。
-
CountDownLatch維護了一個計數器 cnt,每次調用 countDown() 方法會讓計數器的值減 1,減到 0 的時候,那些因爲調用 await() 方法而在等待的線程就會被喚醒。
1.2 CountdownLatch使用例子
package com.yuanxw.chapter12;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.IntStream;
public class CountdownLatchExample {
/** 隨機數:使用long參數的所有64位作爲因子值。 **/
private static Random random = new Random(System.currentTimeMillis());
/** 總線程數 **/
private static final int TOTAL_THREAD_NUMBER = 5;
/** 通過線程池,創建5個線程 **/
private static ExecutorService executorService = Executors.newFixedThreadPool(TOTAL_THREAD_NUMBER);
/** 創建CountDownLatch對象 **/
private static CountDownLatch countDownLatch = new CountDownLatch(TOTAL_THREAD_NUMBER);
public static void main(String[] args) throws InterruptedException {
IntStream.range(0,5).forEach(i->{
executorService.execute(()->{
doWorking();
/** 將count值減1 **/
countDownLatch.countDown();
});
});
/** 當前線程等到鎖存器計數到零 **/
countDownLatch.await();
executorService.shutdown();
System.out.println("所有線程工作已經執行完成!!!");
}
/**
* 模擬工作方法
*/
private static void doWorking(){
try {
System.out.println(String.format("線程【%s】工作>>開始", Thread.currentThread().getName()));
Thread.sleep(random.nextInt(1000));
System.out.println(String.format("線程【%s】工作<<結束", Thread.currentThread().getName()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
執行結果:
線程【pool-1-thread-2】工作>>開始
線程【pool-1-thread-5】工作>>開始
線程【pool-1-thread-3】工作>>開始
線程【pool-1-thread-4】工作>>開始
線程【pool-1-thread-1】工作>>開始
線程【pool-1-thread-4】工作<<結束
線程【pool-1-thread-2】工作<<結束
線程【pool-1-thread-3】工作<<結束
線程【pool-1-thread-1】工作<<結束
線程【pool-1-thread-5】工作<<結束
所有線程工作已經執行完成!!!
– 以上爲《JAVA多線程(十二)Java多線程之CountDownLatch》,如有不當之處請指出,我後續逐步完善更正,大家共同提高。謝謝大家對我的關注。
——厚積薄發(yuanxw)