摘要
本文主要介紹Java多線程並發中閉鎖(Latch)的基本概念、原理、示例代碼、應用場景,通過學習,可以掌握多線程並發時閉鎖(Latch)的使用方法。
概念
「閉鎖」就是指一個被鎖住了的門將線程a擋在了門外(等待執行),只有當門打開後(其他線程執行完畢),門上的鎖才會被打開,a才能夠繼續執行。
閉鎖(Latch),目的是使多個線程在完成各自任務後,才會打開繼續執行後面的任務,否則一直等待。
計數器閉鎖(CountDownLatch)是一個同步工具類, 可以用來協調多個線程的執行時間,允許一個或多個線程等待某個事件的發生。
CountDownLatch有個正數的計數器,countDown(); 對計數器做減法操作,await(); 等待計數器等於0。所有await的線程都會阻塞,直到計數器為0或者等待線程中斷或者超時。
例如, 可以讓a線程在其他線程運行完畢後再執行。如果其他線程沒有執行完畢,則a線程就會一直等待。
原理分析
CountDownLatch的實現原理:
1、CountDownLatch在創建時, 會指定一個計數器,表示等待線程的執行數量(比如,3就表示當3個線程執行完畢後,再結束閉鎖,使a能夠繼續執行);
2、 其他每個線程在各自執行完畢時, 分別調用一次countDown())方法,用來遞減計數器, 表示有一個線程已經執行完畢了;這時, 線程a可以調用await()方法, 用來等待計數器的值為0。
3、如果計數器的值大於0, 那麼await()方法會一直阻塞, 直到計數器為0時,線程a才會繼續執行;
4、如果線程a一直無法等到計數器為0,則會顯示等待超時,當然也可以在線程a等待時,通過程序中斷等待。
示例代碼
在Java中, 可以使用CountDownLatch實現多線程閉鎖,具體實現代碼如下:
public class JavaLearnsCountDownLatch {
public static void main(String[] args) {
//計數器為8
CountDownLatch countDownLatch = new CountDownLatch(8);
//將CountDownLatch對象傳遞到線程的run()方法中,當每個線程執行完畢run()後就將計數器減1
MyThread myThread = new MyThread(countDownLatch);
long start = System.currentTimeMillis();
//創建8個線程,並執行
for (int i = 0; i <8; i++) {
new Thread(myThread).start();
}
try {
//主線程(main)等待:等待的計數器為0;即當CountDownLatch中的計數器為0時,Main線程才會繼續執行。
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("耗時:" + (end - start));
}
}
class MyThread implements Runnable {
private CountDownLatch latch;
public MyThread(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void run() {
try {
Thread.sleep(5000);
}catch (InterruptedException e){
e.printStackTrace();
}
finally {
latch.countDown();//每個子線程執行完畢後,觸發一次countDown(),即計數器減1
}
}
}
應用場景
1、確保某個計算,在其需要的所有資源都準備就緒後再執行,比如:要計算某個工程材料的合價,要知道材料的單價和工程量後,才能執行材料合價計算。
2、確保某個服務,在其依賴的所有其他服務都已經啟動後再啟動。
3、確保某個任務,在所有參與者都準備就緒後再執行,比如:線上上課,在全班30個同學都全部上線後,老師才能開始上課。
我是一名碼齡10年的程式設計師,在這裡會分享實在乾貨,讓你少走彎路,成就精彩人生。