3

即使在通知当前线程(使用此)之后,以下代码也不会执行。

public synchronized void test() {
    String str = new String();
    try {
        System.out.println("Test1");
        this.wait();
        this.notifyAll();
        System.out.println("Test2");
    } catch (Exception e) {
        // TODO Auto-generated catch block
        System.out.println("Inside exception");
        e.printStackTrace();
    }
 }

我只Test1在控制台上得到输出。

在第二种情况下,如果我在字符串对象上调用 wait 方法,则会出现异常。原因是字符串类对象str没有锁定当前对象。但我想知道str.wait()实际上是什么意思?

public synchronized void test() {
    String str = "ABC";
    try {
        System.out.println("Test1");
        str.wait();
        str.notifyAll();
        System.out.println("Test2");
    } catch (Exception e) {
        // TODO Auto-generated catch block
        System.out.println("Ins");
        e.printStackTrace();
    }
 }

控制台输出:

> Test1  
java.lang.IllegalMonitorStateException
4

5 回答 5

7

不确定您对该代码的期望:

  1. 在您的第一个示例中,wait执行它所说的:它等待,因此notifyAll永远不会被调用
  2. 在第二个示例中,您不能wait在不先持有该对象的监视器的情况下调用该对象。所以你需要在一个synchronized(str)块中以避免异常。但是您仍然会遇到与 1 中相同的问题。

waitand的主要用例notify是线程间通信,即一个线程等待,另一个线程通知等待的线程可以唤醒。在您的情况下,相同的线程位于通信通道的两端,这不起作用。

于 2012-12-21T12:19:00.173 回答
3

wait()您应该学习如何notify()正确使用:来自 Effective Java (Josh Bloch):

// The standard idiom for using the wait method
synchronized (obj) {
    while (<condition does not hold>)
    obj.wait(); // (Releases lock, and reacquires on wakeup)
    ... // Perform action appropriate to condition
}

这使得当前线程正确地等待条件变为真。其他线程应该调用notify()或者notifyAll()当这个条件变为真时。

然而,来自 Josh 的更重要的建议是:Prefer concurrency utility to waitand notify

于 2012-12-21T12:30:07.350 回答
3

你不应该在同一个线程中一个接一个地wait调用。notify它们应该从不同的线程执行。如果您等待某些东西,则该控件不会在该线程中继续进行,直到某个其他线程将通知它

于 2012-12-21T12:18:58.973 回答
0

关于您的第一种情况: wait 导致您当前的线程等待,直到另一个线程调用 notify() 方法或 notifyAll() 方法。因此,除非您在另一个线程中执行此操作,否则永远不会调用 notify all。

于 2012-12-21T12:21:05.733 回答
0

在您的第一个片段中,当您调用wait. notifyAll没有执行,因为tread已经在等待。

通知需要在另一个线程上执行。

于 2012-12-21T12:23:43.317 回答