P7資深架構師帶你分析的Thread.join的做用和原理

P7資深架構師帶你分析的Thread.join的做用和原理

 

文章簡介面試

不少人對的Thread.join的做用以及實現瞭解得不多,畢竟這個API咱們不多使用。這篇文章仍然會結合使用及原理進行深度分析多線程

內容導航架構

  • 的Thread.join的做用
  • 的Thread.join的實現原理
  • 何時會使用的Thread.join

1、的Thread.join的做用

以前有人問過我一個這樣的面試題學習

Java的中如何讓多線程按照本身指定的順序執行?this

這個問題最簡單的回答是經過的Thread.join來實現,長此以往就讓不少人誤覺得的Thread.join是用來保證線程的順序性的。spa

下面這段代碼演示了的Thread.join的做用線程

P7資深架構師帶你分析的Thread.join的做用和原理

 

上面的代碼,注意部分,你們能夠把這行代碼註釋之後看看運行效果,在沒有加加盟的時候運行的結果是不肯定的。加了加入之後,運行結果按照遞增的順序展現出來。previousThread.join感興趣的能夠加入個人學習圈子:142019080 視頻

的Thread.join的含義是當前線程須要等待previousThread線程終止以後才從的Thread.join返回。簡單來講,就是線程沒有執行完以前,會一直阻塞在加入方法處。對象

下面的圖表現了加盟對於線程的做用blog

 

P7資深架構師帶你分析的Thread.join的做用和原理

 

2、的Thread.join的實現原理

線程是如何被阻塞的?又是經過什麼方法喚醒的呢?先來看看的Thread.join方法作了什麼事情

P7資深架構師帶你分析的Thread.join的做用和原理

 

從加入方法的源碼來看,加入方法的本質調用的是對象中的等待方法實現線程的阻塞,等待方法的實現原理咱們在後續的文章再說詳細闡述。可是咱們須要知道的是,調用等方法必需要獲取鎖,因此加入方法是被同步的修飾的,同步的修飾在方法層面至關於同步(這),這就是previousThread自己的實例。

有不少人不理解加入爲何阻塞的是主線程呢?不理解的緣由是阻塞主線程的方法是放在previousThread這個實例做用,讓你們誤覺得應該阻塞previousThread線程。實際上主線程會持有previousThread這個對象的鎖,而後調用等方法去阻塞,而這個方法的調用者是在主線程中的。因此形成主線程阻塞。感興趣的能夠加入個人學習圈子:142019080

第二個問題,爲何previousThread線程執行完畢就可以喚醒住線程呢?或者說是在何時喚醒的?

要了解這個問題,咱們又得翻JDK的源碼,可是若是你們對線程有必定的基本瞭解的話,經過等方法阻塞的線程,須要經過通知或者notifyAll的來喚醒。因此在線程執行完畢之後會有一個喚醒的操做,只是咱們不須要關心。

接下來在熱點的源碼中找到,看看線程退出之後有沒有作相關的事情來證實咱們的猜測。thread.cpp

P7資深架構師帶你分析的Thread.join的做用和原理

 

一下觀察這行代碼上的註釋,喚醒處於等待的線程對象,這個是在線程終止以後作的清理工做,這個方法的定義代碼片斷以下ensure_join(this)

P7資深架構師帶你分析的Thread.join的做用和原理

 

ensure_join方法中,調用喚醒全部等待thread鎖的線程,意味着調用了加入方法被阻塞的主線程會被喚醒;到目前爲止,咱們基本上對聯的原理作了一個比較詳細的分析lock.notify_all(thread);

總結,的Thread.join其實底層是經過等待/ notifyAll的來實現線程的通訊達到線程阻塞的目的;當線程執行結束之後,會觸發兩個事情,第一個是設置本地線程對象爲空時,第二個是經過notifyAll的方法,讓等待在previousThread對象鎖上的等待方法被喚醒。

3、何時會使用的Thread.join

在實際應用開發中,咱們不多會使用的Thread.join。在實際使用過程當中,咱們能夠經過加入方法來等待線程執行的結果,其實有點相似將來/調用的功能。

咱們經過如下僞代碼來講明加入的使用場景

P7資深架構師帶你分析的Thread.join的做用和原理

 

 

《架構師資料》領取方法

下圖中的資料都是我精心錄製視頻,感興趣的能夠加入個人學習圈子:142019080 免費獲取。

P7資深架構師帶你分析的Thread.join的做用和原理

相關文章
相關標籤/搜索