因此,我正在开发一个多线程,它将多条命令(命令设计模式)从客户端发送到服务器,然后在那里执行它们并将响应发送回去。
客户端使用java.nio.channels.DatagramChannel
通过UDP发送和接收。
在主线程中,我有一个while(true)读取客户端编写的命令并将其发送到服务器,然后进行处理(db请求,文件更改等)并发送回响应,在始终处于活动状态的线程中等待响应。
该系统可以正常工作,直到服务器关闭(如UDP)为止,“不可能”知道服务器何时处于活动,就绪,启动等状态。因此,我尝试确定服务器是否处于“关闭”状态那就是说,如果在发送请求的一秒钟后没有答案,则客户端部分将进入无限循环,该循环每2秒“尝试”连接一次,并发送命令“ connect”直到收到肯定的响应。
由于必须将接收器线程与主线程分开使用,所以我无法在发送请求后一秒钟准确地计算出请求,因为它是分开运行的,也许必须有一种方法可以使主线程响应,如果超过一秒钟,那么他应该像我之前说的那样重试连接。我读到Thread有一些wait()
notify()
方法可能会帮助我,但是我不确定在我的情况下如何使用它们。代码是向下的。
ClientMain.java
while(true) {
if (channel.isConnected())
reader.startInteraction(currentUser.getCredentials());
else
channel.tryToConnect(address);
responseHandler.checkForResponse();
}
ClientResponseHandler.java,此类具有接收方线程作为内部类
public void checkForResponse() {
startRequestTime = System.currentTimeMillis();
Object received = receiverThread.receivedObject;
if (received instanceof String && received.equals("connect")) {
channel.setConnected(true);
System.out.println("Successfully connected to the server");
}
synchronized (this) {
if (received != null) {
flagReceived = true;
printResponse(received);
} else {
flagReceived = false;
}
receiverThread.receivedObject = null;
}
}
在ReceiverThread.java中,receivedObject
是Thread类内部的易失对象
...
protected volatile Object receivedObject = null;
...
public void run() {
while(true)
receiveData();
}
public void receiveData() throws IOException, ClassNotFoundException {
synchronized (ClientResponseHandler.class) {
//[MARKET]condition that doesn't work protertly
if (channel.requestWasSent() && !flagReceived && System.currentTimeMillis() - startRequestTime > 1000) {
channel.setConnectionToFalse();
}
}
final ByteBuffer buf = ByteBuffer.allocate(AbsUdpSocket.DATA_SIZE);
final SocketAddress addressFromServer = channel.receiveDatagram(buf);
buf.flip();
byte[] bytes = new byte[buf.remaining()];
buf.get(bytes);
if (bytes.length < 1)
return;
synchronized (ClientResponseHandler.class) {
channel.setRequestSent(false);
if (bytes.length < AbsUdpSocket.DATA_SIZE)
receivedObject = processResponse(bytes);
else
throw new EOFException();
}
}
//The processResponse() is just to convert the received bytes to the needed object
标记的情况是应该重新连接我的代码的魔术,但不起作用。有时,他会在成功请求后重新连接,或者在客户端启动且服务器始终处于启动状态时尝试连接3-4次。并且只有在服务器关闭时才尝试第二次执行命令后重新连接。