Java notify()在wait()之前被调用
问题描述:
另一个线程中的notify()在一个线程中的wait()之前被调用吗? 这发生在我身上。Java notify()在wait()之前被调用
客户端从目标请求值并等待结果变量RV。 如果目标是客户端本身,我用正确的结果更新RV,并在另一个线程的RV上调用notify()。
class EMU {
ResultVar RV;
Address my_address;
ResultVar findValue(String key) {
String tgt = findTarget(key);
sendRequest(tgt, key);
synchronized(RV) {
RV.wait();
}
return RV;
}
Runnable Server = new Runnable() {
public void run() {
//code to receive connections. Assume object of type Request is read from the stream.
Request r = (Request) ois.readObject();
if(r.requesterAddr.compareTo(my_address) == 0) {
String val = findVal(key);
RV.putVal(val);
synchronized(RV){
RV.notify();
}
}
}
};
}
的问题是,请求者已经完成所有的“网络”(sendReqest在上面的例子)与自身之前,其结果是在结果变量更新。当请求者线程现在调用wait()时,程序不会继续,因为notify已经被调用。
我们该如何预防?
答
你等待(在一个循环中)之前检查一些标志,请参阅教程:http://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html
答
我们无法阻止你,不是被wait
被另一个线程编的对象上调用notify
。
这听起来像你想要的只是一个等待,如果一些条件成立。例如:
synchronized (results) {
while (!results.hasResults()) {
// no results yet; wait for them
try {
results.wait();
} catch (InterruptedException ie) { /* ignore */ }
}
}
答
我强烈建议不要重新发明车轮。
Java的Future接口是专门为可能会晚到的结果而设计的,并且FutureTask类实现此接口。
让第一个线程获得对Future的访问权并获得第二个线程来运行FutureTask,并且所有这些东西都可以为您处理。您也可以免费获得超时支持。
答
使用之前要等待(),并确保该条件是线程安全的:)
class EMU{
ResultVar RV;
Address my_address;
volatile boolean condition = true;
ResultVar findValue(String key){
String tgt = findTarget(key);
sendRequest(tgt, key);
synchronized(RV){
while(condition == true)
{
RV.wait();
}
}
return RV;
}
Runnable Server = new Runnable(){
public void run(){
//code to receive connections. Assume object of type Request is read from the stream.
Request r = (Request) ois.readObject();
if(r.requesterAddr.compareTo(my_address) == 0){
String val = findVal(key);
RV.putVal(val);
synchronized(RV){
condition = false;
RV.notify();
}
}
}
};
'如果目标是itself'你的意思是这里的客户端的一些情况?你可以把一些代码示例? – Cratylus
@shishir garg能否请你粘贴一些代码 –
没有看到代码就很难回答 - 尽管有2条评论:a)通常使用notifyAll比通知更好,除非你知道你在做什么b)使用wait和通知可能容易出错,您应该使用更高级别的并发API,除非您需要非常具体的东西。 – assylias