Java多執行緒/併發07、Thread.Join()讓呼叫執行緒等待子執行緒

唐大麥發表於2017-04-28

開始之前,有幾點要理解的:
1、當程式執行的時侯,系統預設開啟了一個主執行緒(假設命名mainThread)。通常我們在Main()函式中定義主執行緒的工作。
2、可以在Main()函式中啟動多個子執行緒:Thread-1,Thread-2,Thread-3等。
3、主執行緒有可能比子執行緒先結束執行。

第三點是關鍵,這也是要用到join()方法的一個重要原因,因為有時侯我們希望主執行緒等待子執行緒執行完成之後再結束。
看一個例子:在主執行緒中開啟一個子執行緒,用來計算1至100的和,然後在主執行緒中列印出來

package JConcurrence.Study;

public class JoinDemo {
    static int result = 0;
    public static void main(String[] args) {
        Thread subThread = new Thread() {
            @Override
            public void run() {
                for (int i = 1; i <= 100; i++) {
                    result = result + i;
                    /*模擬耗時操作*/
                    try {
                        Thread.sleep(20);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        subThread.start();
        System.out.print(result);
    }
}

程式執行結果:

1到100求和結果等於:0

出錯了。程式執行進入Main()函式後,開啟子執行緒subThread計算求和。此時主執行緒並沒有停止,繼續往下執行。子執行緒subThread執行耗時大約2秒,而主執行緒如出膛子彈迅速往下執行完畢。子執行緒此該還沒有反應過來,主執行緒已經輸出了結果。

為了輸出正確的結果,顯而易見,必須讓主執行緒等待子執行緒執行完畢再執行System.out.print。
這時,輪到Thread.Join()出場了。
在subThread.start()和System.out.print(result)之間加上

try {
    subThread.join();
} catch (InterruptedException e) {
    e.printStackTrace();
}

程式執行結果:

1到100求和結果等於:5050

結果正確!

Join()方法中可以設定值,即等待多久。比如上面如果把subThread.join()改為subThread.join(1000),就是告訴主執行緒等待子執行緒1秒鐘後再繼續執行。你可以這樣修改後試著執行一下程式,這時程式輸出的應該是0到5050間的一個值。

注意事項

在多個子執行緒的情況下,若依次執行每個執行緒的start()和join()方法,則各個執行緒之間是同步的。

for(int i=1;i<=3;i++){
    Thread subThread = new Thread(new workrun(i));
    subThread.start();
    subThread.join();
}

上面程式中的三個子執行緒會順序同步的執行。
要想三個子執行緒能夠併發執行,需要改變join呼叫位置

Thread subThread1 = new Thread(new workrun(1));
Thread subThread2 = new Thread(new workrun(2));
Thread subThread3 = new Thread(new workrun(3));

subThread1.start();
subThread2.start();
subThread3.start();

subThread1.join();
subThread2.join();
subThread3.join();

相關文章