2013-05-03 104 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