多線程併發比較常見,但不少時候一個線程的輸入可能很是依賴於另一個線程的輸出,此時這個線程就須要等待依賴線程執行完畢再執行。通俗的說,就是合併多個路徑爲單一路徑,變多線程併發爲單線程順序執行。JDK提供了Join()這個Thread類的實例方法來達到這個要求。java
join——英文含義爲加入,通俗的說就是將一個線程合併到另外一個線程。可是還有如下幾個問題:多線程
哪一個線程加入?併發
加入到哪一個線程?
ide
加入後的效果是啥?函數
經過下面一段代碼能夠進行驗證:spa
public class JoinTest extends Thread { private static int i = 0; @Override public void run() { while (i < 100000) { i++; } } public static void main(String[] args) throws Exception { Thread th = new JoinTest(); //注意:必須先start,再join th.start(); th.join(); System.out.println(i); } }
執行結果爲:100000 線程
驗證後能夠回答上面三個問題了。code
哪一個線程加入?——>調用Join()函數的那個對象開啓的線程,注意要先開啓線程,才能加入start,也就是start()方法要在join()方法前面。本例中是對象
JoinTest
加入到哪一個線程?——>加入到當前線程,通俗的說在哪一個線程中執行該函數的,就加入哪一個線程。同步
本例中是
main
加入後的效果?——>阻塞當前線程,直到加入的線程執行完,當前線程繼續執行。
join的本質是讓當前線程wait()在調用join方法的那個線程實例的鎖上,等到那個線程實例開啓的線程跑完,再notify()當前線程繼續執行。下面是JDK中join()實現的核心代碼片斷:
public final synchronized void join(long paramLong) throws InterruptedException { long l1 = System.currentTimeMillis(); long l2 = 0L; if (paramLong < 0L) throw new IllegalArgumentException("timeout value is negative"); //過時時間爲0 if (paramLong == 0L) while (true) { //isAlive()是一個實例方法,用來判斷線程(不是當前main線程, //而是含有該方法的線程實例JoinTest啓動的那個線程)是否存活,通俗的說就是run方法有沒有跑完 if (!(isAlive())) return; //這裏是關鍵,同步方法內調用鎖對象的wait()方法阻塞當前線程 //可能這裏會有疑問,阻塞的難道不是JoinTest線程嗎?你看,是JoinTest對象裏的方法 //是否是JoinTest線程要看它在不在run方法裏面,這個函數在run方法裏面嗎?顯然不是 super.wait(0L);//被合併線程未結束,當前線程繼續等待 } while (isAlive()) { long l3 = paramLong - l2; if (l3 <= 0L) return; super.wait(l3); l2 = System.currentTimeMillis() - l1; } }
以後的流程咱們也能猜到,被合併的線程執行完後,會notify()【其實這裏是notifyall()】等待線程繼續執行。