1. 程式人生 > >等待線程結束(join)

等待線程結束(join)

等待時間 isa 線程 exc volatile 函數 ati 合作 static

  很多情況下,線程之間的協作和人與人之間的協作非常相似。一種非常常見的合作方式就是分工合作。以我們非常熟悉的軟件開發為例,在一個項目進行時,總是應該有幾位號稱是“需求分析師”的同事,先對系統的需求和功能點進行整理和總結,然後,以書面形式給出一份需求說明或者類似的參考文檔,然後,軟件設計師,研發工程師才會一擁而上,進行軟件開發。如果缺少需求分析師的工作輸出,那麽軟件研發的難度可能會比較大。因此,作為一名軟件研發人員,總是喜歡等待需求分析師完成他應該完成的任務後,才願意投身工作。簡單地說,就是研發人員需要等待需求分析師完成他的工作,然後,才能進行研發。

  將這個關系對應到多線程應用中,很多時候,一個線程的輸入可能非常依賴於另外一個或者多個線程的輸出,此時,這個線程就需要等待依賴線程執行完畢,才能繼續執行,JDK提供了join()操作來實現這個功能。下邊顯示兩個join方法:

public final void join() throws InterruptedException
public final synchronized void join(long millis) throws InterruptedException

  第一個join方法表示無線等待,他會一直阻塞當前線程,知道目標線程執行完畢。第二個方法給出了一個最大等待時間,如果超過給定時間目標線程還在執行,當前線程也會因為“等待不及了”,而繼續往下執行。

  英文join的翻譯,通常是加入的意思。在這裏感覺也非常貼切。因為一個線程要加入另外一個線程,那麽最好的方法就是等著它一起走。

  這裏提供一個join實例:

public class JoinMain{
    public volatile static int i = 0 ;
    public static class AddThread extends Thread{
        public void run(){
            for(i=0;i<10000000;i++);
        }
    }
    public static void main(String args[]) throws InterruptedException{
        AddThread at = new AddThread();
        at.start();
        at.join();
        System.out.println(i);
    }
}

  主函數中,如果不使用join()等待AddThread,那麽得到的i很可能是0或者一個非常小的數字。因為AddThread還沒開始執行,i的值就已經唄輸出了。但在使用join()方法後,表示主線程願意等待AddThread執行完畢,跟著AddThread一起往前走,故在join()返回時,AddThread已執行完成,故i總是10000000.

  有關於join().我還想再補充一點,join()的本質是讓調用線程wait()在當前線程對象實例上。下面是JDK中join()實現的核心代碼片段

while(isAlive()){
    wait(0);
}

  可以看到,它讓調用線程在當前線程對象上進行等待。當線程執行完成後,被等待的線程會在退出前調用notifyAll()通知所有的等待線程繼續執行。因此,值得註意的一點是:不要在應用程序中,在Thread對象實例上使用類似wait()或者notify()等方法,因為這很有可能會影響系統API的工作或者被系統API影響。

等待線程結束(join)