join()——化多線程併發執行爲順序執行

多線程併發比較常見,但不少時候一個線程的輸入可能很是依賴於另一個線程的輸出,此時這個線程就須要等待依賴線程執行完畢再執行。通俗的說,就是合併多個路徑爲單一路徑,變多線程併發爲單線程順序執行。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()】等待線程繼續執行。

相關文章
相關標籤/搜索