object.notify()不会唤醒object.wait()

时间:2013-02-14 20:29:13

标签: java multithreading

我正在尝试使用“synchronized(object) {object.wait()}”暂停我的服务器直到对象准备就绪。我在类中调用了'synchronized(object) {object.notify() }'来设置对象值。但似乎我的服务器永远不会在wait()之后醒来。

public class MyServer {
...
do {
            try {

                message = (String) in.readObject();
                System.out.println("server receive>" + message);

                synchronized (myServerSend) {
                    myServerSend.wait();
                }

                System.out.println("Am I wake up???"); //this never print out

                sendMessage(myServerSend);

            } catch (ClassNotFoundException classnot) {
                System.err.println("Data received in unknown format");
            }
        } while (!message.equals("bye"));

    } catch (IOException ioException) {
        ioException.printStackTrace();
    }
....
}

以下是我设置对象值

的要求
public class Action implements MouseInputListener, MouseMotionListener {

    ....

    public void mouseClicked(MouseEvent e) {


        if (SwingUtilities.isLeftMouseButton(e)) {...
    }

        else {
            ....
            if(MyGame.currentPlayer == MyGame.WHITE) {
                    myServerSend = "" + chosenPieceIndex + "," + moveLocationIndex;
                    synchronized (myServerSend) {

                        myServerSend.notify(); // this seems like fail to wake up myServer

                    }
                    System.out.println(myServerSend);
}

如果我将myServerSend声明为公共静态字符串类型,会不会有问题? 任何人都可以帮忙吗?提前谢谢!

3 个答案:

答案 0 :(得分:2)

也许你在等待之前得到了通知代码。因为这个原因,你应该总是把thread.wait()放在while循环中(并且由于虚假唤醒 - 但是由于这个原因,同时做得足够好)。

答案 1 :(得分:0)

虽然我不确定您的代码到底出了什么问题,但代码本质上是不安全的。如果没有别的,则无法保证wait()之前的notify()调用 - 如果先发生通知,等待将永远持续。另外,wait may wake up spuriously,所以即使你修复了,你仍然没有正确的代码:

  

线程也可以在没有被通知,中断或者被唤醒的情况下被唤醒   超时,即所谓的虚假唤醒。虽然这很少发生   在实践中,应用程序必须通过测试来防范它   应该导致线程被唤醒的条件,以及   如果条件不满意,继续等待。换一种说法,   等待应该总是出现在循环中,如下所示:

 synchronized (obj) {
     while (<condition does not hold>)
         obj.wait(timeout);
     ... // Perform action appropriate to condition
 }

您可以考虑将此代码替换为CountDownLatchCyclicBarrier或甚至Semaphore。这些类更容易使用并且不易出错。 wait / notify是较低级别,有些难以正确使用。

答案 2 :(得分:0)

在没有看到所有代码的情况下给出明确答案有点困难,但问题可能在于:

myServerSend = "" + chosenPieceIndex + "," + moveLocationIndex;
synchronized (myServerSend) {
    myServerSend.notify(); // this seems like fail to wake up myServer
}

您确定此对象(myServerSend)确实与MyServer.myServerSend对象相同吗?看起来myServerSend是在Action类中创建的,从你描述的预期顺序是MyServer然后是Action,但正如我所说myServerSend似乎是在MyServer中创建的。

换句话说,如果evens的顺序应该是MyServer,那么Action我希望锁定对象可以在两者之外创建,也可以在MyServer类中创建。

所以猜测我会说你没有在同一个对象上进行同步,如果这是真的,它会解释你所看到的行为。

但是,如果您确定这是同一个对象,则事件的顺序必须为Action,然后是MyServer(或者您在MyServer中获得NullPointerException),如果是这样的情况我我猜你在等待之前就已经通知了,所以你的代码永远停留在等待点,等待已经错过的通知。