1

我正在尝试让用户 ' 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 声明为公共静态字符串类型会不会有问题?有人可以帮忙吗?提前致谢!

4

3 回答 3

2

也许你在等待之前得到了通知代码。出于这个原因,您应该始终将 thread.wait() 放在 while 循环中(也由于虚假唤醒 - 但出于这个原因,while 就足够了)。

于 2013-02-14T20:38:55.363 回答
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 中创建的。

换句话说,如果事件的顺序应该是 MyServer 然后是 Action 我会期望锁定对象在两者之外创建,或者在 MyServer 类中创建。

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

但是,如果您确定这是同一个对象,那么事件的顺序必须是 Action,然后是 MyServer(或者您会在 MyServer 中获得 NullPointerException),如果是这样,我猜您是在通知您之前等待,因此您的代码将永远停留在等待点,等待它已经错过的通知。

于 2013-02-14T21:22:14.850 回答
0

虽然我不确定您编写的代码到底有什么问题,但代码本质上是不安全的。如果没有别的,就不能保证调用wait()发生在之前notify()——如果先发生通知,则等待将永远持续。此外,等待可能会被虚假唤醒,因此即使您修复了该问题,您仍然不会有正确的代码:

线程也可以在没有被通知、中断或超时的情况下唤醒,即所谓的虚假唤醒。虽然这在实践中很少发生,但应用程序必须通过测试应该导致线程被唤醒的条件来防范它,如果条件不满足则继续等待。换句话说,等待应该总是在循环中发生,就像这样:

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

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

于 2013-02-14T20:48:21.443 回答