在Java

时间:2015-06-02 13:08:09

标签: java multithreading wait synchronized

我正在使用java.lang.Object中定时版本的wait(),并观察到它在两种不同的场景中表现不同。

场景1:在线程中使用run()的默认定义

public static void main (String[] args) throws InterruptedException {
    Thread t = new Thread();    
    t.start();
    System.out.print("X");
    synchronized(t) { t.wait(10000);}
    System.out.print("Y");
}

关于scenario1的问题:我遇到了X和Y之间的延迟。这是因为我从main调用wait()(即使在t上)因此调用主要的调用堆栈正在使用线程,而不是第二个线程的线程?

场景2: 动态对线程进行子类化以覆盖run()以打印内容。

public static void main (String[] args) throws InterruptedException {
     Thread t = new Thread() {public void run() 
                     {System.out.print("I am the second thread.");}};
     t.start();
     System.out.print("X");
     synchronized(t) { t.wait(10000);}
     System.out.print("Y");
}

关于scenario2的问题:我根本没有遇到任何延迟!是什么改变只是因为我已经覆盖了run()?现在,每次我运行程序时,它都会立即打印出“XI am the second thread.Y”,无论如何! wait()的效果在哪里消失了?

2 个答案:

答案 0 :(得分:7)

您实际上已经遇到了为什么不应该在Thread上调用waitnotify(All)的原因(请参阅JavaDocs for Thread)。在内部,Thread使用wait和notifyAll来实现Thread.join(),所以在第二种情况下发生的是线程进入等待,但随后另一个线程死掉并调用notifyAll(),它唤醒你的主线程。

如果您只想等待一段时间,请使用Thread.sleep,如果您确实想要等待线程终止,请使用Thread.join。另外,请阅读Object中的javadocs,以正确使用waitnotifynotifyAll

javaDoc

public final void join(long millis)
                throws InterruptedException
     

此线程最多等待毫秒毫秒。暂停时间   0意味着永远等待。此实现使用this.wait的循环   以此为条件的电话.isAlive。 作为一个线程终止   this.notify调用所有方法。建议应用程序   不要在线程实例上使用wait,notify或notifyAll。

答案 1 :(得分:1)

explanation about how the thread finishing sends a notifyAll是相关且正确的,+1来自我。我会尝试添加一些有关其相关原因的信息。

致电时

Dim objFSO
Set objFSO = CreateObject("Scripting.FileSystemObject")

Dim objFile, strNewestFile, dtmMax
For Each objFile In objFSO.GetFolder("C:\CSV\Test\CSVOriginal").Files
    If objFile.DateLastModified > dtmMax Then
        dtmMax = objFile.DateLastModified
        strNewestFile = objFile.Path
    End If
Next

objFSO.GetFile(strNewestFile).Copy "C:\CSV\Test\CSVFlytt\"

在主线程中,它是执行等待的主线程。 synchronized(t) { t.wait(10000);} 是主线​​程正在等待的监视器。

,你的期望是这会让你的t线程处于休眠状态。

这里的监视器(被锁定的共享对象,恰好是t)用于在不同的线程之间进行通信,一个线程在监视器上调用notifyAll,而在监视器上等待的其他线程接收到通知。您可以将监视器视为共享通信点。

在你的第一个例子中,线程t立即开始并结束(因为它没有任何事情可做)。线程在主线程开始等待之前完成并发送其通知,因此您会看到延迟直到等待超时。

在第二个例子中,线程t有要打印的东西,它与主线程之间存在竞争条件。它是一个免费的,首先发生的事情取决于计时事故。您所看到的是线程t现在必须在控制台上打印一条线,因此它设法保持足够长的时间以使其在主线程开始时仍处于活动状态。等待,允许主线程在t完成时接收通知,导致主线程缩短等待时间。