这是我的代码。它应该实现一种在分布式系统中同步调用的方法。这是我发送消息并等待确认的部分。网络和同行被认为是可靠的。
我的问题虽然与本地同步有关,因为它不断引发此异常,我无法理解原因。
Exception in thread "Thread-7" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:503)
at distributed.PeerManager.sendAllWithAck(PeerManager.java:212)
at distributed.TokenManager.onTokenReceived(TokenManager.java:67)
at communication.TokenMessage.execute(TokenMessage.java:21)
at distributed.ListenThread.run(ListenThread.java:38)
Exception in thread "Thread-8" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at distributed.AckWaiter.run(AckWaiter.java:74)
这是AckWaiter类:
public class AckWaiter extends Thread {
public int counter;
PeerManager pm;
Message m;
public Object waiter;
public int parentPort;
public AckWaiter(PeerManager pm, Message m, int n,int parentPort) {
counter = n;
this.pm = pm;
this.m = m;
this.parentPort=parentPort;
waiter=new Object();
}
public synchronized void notifyAck() {
counter--;
notify();
}
@Override
public synchronized void run(){
pm.sendAllExceptMe(m);
try {
BufferedReader inFromClient=new BufferedReader(new
InputStreamReader(pm.listener.socketMap.get(parentPort).getInputStream()));
while(counter>0){
wait(100);
Message m=CustomMarshaller.getCustomMarshaller().unmarshal(inFromClient.readLine());
if(m==null){
continue;
}
m.execute(pm);
}
} catch (IOException | InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
waiter.notify();
return;
}
}
这里的调用应该阻止线程
public synchronized void sendAllWithAck(Message m){
if(aw!=null){
throw new RuntimeException();
}
aw=new AckWaiter(this,m,connectionList.size()-1,m.sender.getPort());
aw.start();
try {
aw.waiter.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
aw=null;
}
'sendAllWithAck'应该启动一个AckWaiter线程,等待对象'服务员',当我收到'n'个ACK时会通知它。
当接收到ACK消息时,通信层调用'notifyAck'方法。
AckWaiter本身就是一个线程,因为'sendAllWithAck'可以由负责从套接字读取的线程调用。我有n个对等体,并且每个对等体都有一个开放套接字(带有处理入站消息的线程),因此如果我等待ACK响应收到的消息,我就无法从那个读取ACK peer(parentPort是该对等体的标识符,因此我可以定期检查此线程内的ACK)。
如果这个异常是由结构性问题引起的,我可以修改我的架构,但我不知道在不修改我的通信层的情况下以不同的方式处理它,这将是一个痛苦。
答案 0 :(得分:1)
方法wait()
,notify()
和notifyAll()
必须位于synchronized
块中。并且run方法只能由一个线程访问(因此不需要同步),并且异常在ListenThread中。