我正在尝试使用“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声明为公共静态字符串类型,会不会有问题? 任何人都可以帮忙吗?提前谢谢!
答案 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 }
您可以考虑将此代码替换为CountDownLatch,CyclicBarrier或甚至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),如果是这样的情况我我猜你在等待之前就已经通知了,所以你的代码永远停留在等待点,等待已经错过的通知。