2013-05-03 56 views
3

我有一個關於基於等待/通知的線程交互的問題。誰在完成後通知線程?

以下代碼的輸出是Im。如何輸出Im,因爲線程對象上沒有其他線程調用notify()。它是否像JVM在上面這種情況下隱式調用notify(),您嘗試在Thread類實例上等待。

線程操作在等待而未收到任何通知時卡住。現在如果我在Thread類實例wait()上等待,該怎麼辦?對於例如

public class WaitingThread { 
    public static void main(String[] args) { 
     Thread t1 = new Thread(); 
     t1.start(); 
     synchronized (t1) { 
      try { 
       t1.wait(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
     System.out.println("Im"); 
    } 
} 

回答

10

您的程序正在離開wait(),因爲線程正在立即完成。這是Thread庫的副產品,線程完成時會通知Thread對象。這是join()的工作方式,但它是而不是應該依賴的行爲,因爲它是線程子系統的內部。

如果您試圖等待線程完成,那麼您應該使用t1.join()方法。

由於沒有run()定義的方法,所以它的啓動和結束會立即完成。真的這是一個競爭條件和啓動的線程可以完成之前主線程到達wait()方法調用。如果在調用start()之後進行了短暫睡眠(可能是10ms),則可以看到這一點。然後你可以看到你的程序將永遠坐在wait()

+0

因此,就像JVM在內部通知您嘗試等待Thread實例的情況下一樣,即使您在Thread類實現中重寫run()並在該特定實例上調用wait,也會得到相同的行爲。 – Hitesh 2013-05-03 15:36:37

+2

對於downvoter:這種行爲自Java 7以來有記錄:http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#join%28long%29 – 2013-05-03 15:37:41

+0

呃是的,但再次,我不認爲這是定義的行爲。這是JVM工作方式的副產品,不應該使用。如果您等待線程完成@ user1841293,則應該使用'join()'。 – Gray 2013-05-03 15:37:58