控制多線程打印順序,你可能只能寫出前三種,最後一種可能想不到

經典面試題

編寫一個程序,開啟三個線程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方法如下:

  1. acquire: 方法阻塞,直到有一個許可證可以獲取然後拿走一個租客正
  2. release: 增加一個許可證,然後釋放一個阻塞acquire的方法

下面用生活場景介紹

比如××馬路要限制流量,只允許同時有一百輛車在這條路上行駛,其他的都必須

在路口等待,所以前一百輛車會看到綠燈,可以開進這條馬路,後面的車會看到紅燈,不能駛

入××馬路,但是如果前一百輛中有5輛車已經離開了××馬路,那麼後面就允許有5輛車駛入馬

路,這個例子裡說的車就是線程,駛入馬路就表示線程在執行,離開馬路就表示線程執行完

成,看見紅燈就表示線程被阻塞,不能執行。

控制多線程打印順序,你可能只能寫出前三種,最後一種可能想不到

實現代碼如下:

控制多線程打印順序,你可能只能寫出前三種,最後一種可能想不到


控制多線程打印順序,你可能只能寫出前三種,最後一種可能想不到

結果為:

控制多線程打印順序,你可能只能寫出前三種,最後一種可能想不到


實現原理:

1、首先讓A有一個許可證,B C 默認為0個

2、如果B或者C獲取執行權,由於沒有許可證,線程執行權會到A手中。

3、A 執行後,由於有許可證,所以代碼可以執行下去。執行完成後,增加B的許可證。

4、B執行,執行完後,增加C的許可證,C執行完成後,增加A的許可證,A線程再次執行。

如果你有不同的見解,歡迎評論!


分享到:


相關文章: