經典面試題
編寫一個程序,開啟三個線程A,B,C , 這三個線程輸出分別為 A、B、C,要求,按順序輸出ABC,
循環10次, 分別為 ABCABCABCABCABC......
下面介紹以下四種實現方式
2.1 用synchronized、wait、notifyAll實現
標準的實現模式如下
1、等待方遵循如下原則。
(1) 獲取對象的鎖。
(2) 如果條件不滿足,那麼調用對象的wait()方法,被通知後仍要檢查條件。
(3) 條件滿足則執行對應的邏輯。
synchronized(對象){
while(條件不滿足){
對象.wait();
}
對應的處理邏輯;
}
2、通知方遵循如下原則。
(1) 獲得對象的鎖。
(2)改變條件。
(3) 通知所有等待在對象上的線程。
synchronized (對象){
改變條件;
對象.notifyAll();
}
實現代碼如下:
測試結果:
實現步驟如下:
1、線程定義每個線程執行的次數
2、A B C 三個線程都需要先獲取鎖,無論誰先獲取線程執行的優先權,Index 最初值為1,如果B 或者 C 先拿到執行權,則判斷後,都會釋放鎖。最終會A拿到執行權。
3、A執行後正好對index 取模 等於1,然後執行,喚醒B和C線程去執行
4、B 和 C線程拿到執行權後,判斷完成後,最終還是B得到執行
5、依次循環下去
2.2 用 ReentrantLock 和 Condition
ReentrantLock 是可重入鎖,支持公平和非公平鎖。
Condition 條件變量,對於每一個Lock,可以由任意數量的Condition對象,
因此對於不同的條件謂詞,對於同一鎖,可以用不同的Condition 對象老控制。
Condition 對象會繼承相關的Lock公平性,對於公平的鎖,線程會一招FIFO 順序從await中釋放。
標準的寫法如下:
實現代碼如下:
測試結果:
實現原理 和 2.1 類似。
2.3 用 ReentrantLock 和 多個Condition
Condition 能夠更加精細的控制多線程的等待和喚醒,並且對於通過一個鎖可以創建多個Condition監視器。
利用不同的Condition對象實現當一個線程結束,喚醒下一個線程。
使用volatile 修飾index, 可以在線程之間保持可見性。
實現代碼如下:
結果:
實現步驟:
1、首先定義一個index區別每個線程。
2、首先 A,B ,C 三個線程同時搶執行權,A的條件是index == 0,B 的條件是 index == 1,
C的條件是 index == 1.
3、滿足條件後,依次進行喚醒。
2.4 用 Semaphore 計數器
Semaphore 是一個計數器信號量,必須由獲取它的線程釋放,通常用於限制可以訪問某些資源。
Semaphore方法如下:
- acquire: 方法阻塞,直到有一個許可證可以獲取然後拿走一個租客正
- release: 增加一個許可證,然後釋放一個阻塞acquire的方法
下面用生活場景介紹
比如××馬路要限制流量,只允許同時有一百輛車在這條路上行駛,其他的都必須
在路口等待,所以前一百輛車會看到綠燈,可以開進這條馬路,後面的車會看到紅燈,不能駛
入××馬路,但是如果前一百輛中有5輛車已經離開了××馬路,那麼後面就允許有5輛車駛入馬
路,這個例子裡說的車就是線程,駛入馬路就表示線程在執行,離開馬路就表示線程執行完
成,看見紅燈就表示線程被阻塞,不能執行。
實現代碼如下:
結果為:
實現原理:
1、首先讓A有一個許可證,B C 默認為0個
2、如果B或者C獲取執行權,由於沒有許可證,線程執行權會到A手中。
3、A 執行後,由於有許可證,所以代碼可以執行下去。執行完成後,增加B的許可證。
4、B執行,執行完後,增加C的許可證,C執行完成後,增加A的許可證,A線程再次執行。
如果你有不同的見解,歡迎評論!
閱讀更多 碼農的一天 的文章