1. 程式人生 > >【Java學習筆記】join()方法

【Java學習筆記】join()方法

方法Join 是幹啥用的? 簡單回答,同步,如何同步? 怎麼實現的? 下面將逐個回答。  

    自從接觸Java 多執行緒,一直對Join 理解不了。JDK 是這樣說的:join public final void join (long millis )throws InterruptedException Waits at most millis milliseconds for this thread to die. A timeout of 0 means to wait forever. 大家能理解嗎? 字面意思是等待一段時間直到這個執行緒死亡,我的疑問是那個執行緒,是它本身的執行緒還是呼叫它的執行緒的,上程式碼: 

 package  concurrentstudy; 
    /** 
    * 
    *  @author  vma 
    */ 
    public   class  JoinTest { 
    public   static   void  main(String[] args) { 
    Thread t =  new  Thread( new  RunnableImpl()); 
    t.start(); 
    try  { 
    t.join(1000) ; // 主執行緒只等1 秒,不管子執行緒什麼時候結束 
    System.out.println("joinFinish"); 
    }  catch  (InterruptedException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
    } 
    } 
    } 
    class  RunnableImpl  implements  Runnable { 
    @Override 
    public   void  run() { 
    try  { 
    System.out.println("Begin sleep"); 
    Thread.sleep(1000); 
    System.out.println("End sleep"); 
    }  catch  (InterruptedException e) { 
    e.printStackTrace(); 
    } 
    } 
    }
結果是:  
    Begin sleep  
    End sleep  
    joinFinish  
    明白了吧, 當main 執行緒呼叫t.join 時,main 執行緒等待t 執行緒 ,等待時間是1000 ,如果t 執行緒Sleep 2000 呢 

 結果是:  
    Begin sleep  
    joinFinish  
    End sleep  
    也就是說 main 執行緒只等1000 毫秒,不管T 什麼時候結束 ,如果是t.join() 呢, 看程式碼: 

就是說如果是t.join() = t.join(0) JDK 這樣說的 A timeout of  0  means to wait forever 字面意思是永遠等待,是這樣嗎?  
    其實是等到t 結束後。

其實Join 方法實現是通過wait (小提示:Object 提供的方法)。 當main 執行緒呼叫t.join 時候,main 執行緒會獲得執行緒物件t 的鎖 (wait 意味著拿到該物件的鎖), 呼叫該物件的wait( 等待時間) ,直到該物件喚醒main 執行緒,比如退出後。  
    這就意味著main 執行緒呼叫t.join 時,必須能夠拿到執行緒t 物件的鎖 ,如果拿不到它是無法wait 的,剛開的例子t.join(1000) 不是說明了main 執行緒等待1 秒,如果在它等待之前,其他執行緒獲取了t 物件的鎖,它等待時間可不就是1 毫秒了。上程式碼介紹:

/* 
    * To change this template, choose Tools | Templates 
    * and open the template in the editor. 
    */ 
    package  concurrentstudy; 
    /** 
    * 
    *  @author  vma 
    */ 
    public   class  JoinTest { 
    public   static   void  main(String[] args) { 
    Thread t =  new  Thread( new  RunnableImpl()); 
    new  ThreadTest(t).start();// 這個執行緒會持有鎖 
    t.start(); 
    try  { 
    t.join(); 
    System.out.println("joinFinish"); 
    }  catch  (InterruptedException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
    } 
    } 
    } 
    class  ThreadTest  extends  Thread { 
    Thread thread; 
    public  ThreadTest(Thread thread) { 
    this .thread = thread; 
    } 
    @Override 
    public   void  run() { 
    holdThreadLock(); 
    } 
    public   void  holdThreadLock() { 
    synchronized  (thread) { 
    System.out.println("getObjectLock"); 
    try  { 
    Thread.sleep(9000); 
    }  catch  (InterruptedException ex) { 
    ex.printStackTrace(); 
    } 
    System.out.println("ReleaseObjectLock"); 
    } 
    } 
    } 
    class  RunnableImpl  implements  Runnable { 
    @Override 
    public   void  run() { 
    try  { 
    System.out.println("Begin sleep"); 
    Thread.sleep(2000); 
    System.out.println("End sleep"); 
    }  catch  (InterruptedException e) { 
    e.printStackTrace(); 
    } 
    } 
    } 

在main 方法中   通過new  ThreadTest(t).start(); 例項化ThreadTest   執行緒物件, 它在 holdThreadLock() 方法中,通過   synchronized  (thread) ,獲取執行緒物件t 的鎖,並Sleep (9000 )後釋放,這就意味著,即使  
    main 方法t.join(1000), 等待一秒鐘,它必須等待 ThreadTest   執行緒釋放t 鎖後才能進入wait 方法中,它實際等待時間是9000+1000 MS  
   執行結果是:  
    getObjectLock  
    Begin sleep  
    End sleep  
    ReleaseObjectLock

    joinFinish