I'm developing a server app which receives RESTful request from clients and send it to a specific device in a new thread (UDP packet). Besides, it runs another thread launched by a servlet listener at the beginning of the execution, which listens the UDP packets sent from all the devices of the system.
When a client make a request from a specific device, the REST service has to launch a thread from where an UDP packet will be sent to the device, and wait for the response. When the UDP server finally receives a packet from that device (checking the ip from the packet), it has to notify the blocked thread to continue its execution and finish.
I thought about using wait()
, notify()
and notifyAll()
methods, but, as many threads can be blocked waiting for the response of several devices, I don't see how could I notify to unblock only the desired thread (the one that made the request on the responding device). Is there a way of doing this using that methods? Any other approach? Here is some code (simplified):
SocketServletListener:
public class SocketServletListener implements ServletContextListener {
private UDPServer server;
private ServletContext context;
@Override
public void contextInitialized(ServletContextEvent sce) {
context = sce.getServletContext();
server = new UDPServer();
server.start();
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
context = sce.getServletContext();
server.interrupt();
}
}
UDPServer:
public class UDPServer extends Thread {
private SocketUDPCommunication comm;
public UDPServer() {
comm = new SocketUDPCommunication();
}
@Override
public void run() {
DatagramPacket response;
try {
comm.setPort(Utils.UDP_SERVER_PORT);
comm.createSocket();
while (!Thread.currentThread().isInterrupted()) {
try {
response = comm.receiveResponse();
} catch (SocketTimeoutException e) {
continue;
}
InetAddress ip = response.getAddress();
int port = response.getPort();
byte[] byteSend = comm.discardOffset(response);
//TODO notify thread which made the request for the responding device (identified by ip)
}
} catch (IOException e) {
System.err.println("Unable to process client request: " + e.getMessage());
} catch (IllegalArgumentException ex) {
System.err.println("Illegal Argument: " + ex.getMessage());
} finally {
comm.closeConnection();
}
}
@Override
public void interrupt() {
super.interrupt();
comm.closeConnection();
}
}
DataSend.java:
@Path("dataSend")
public class DataSend {
@Context
private UriInfo context;
public DataSend() {
}
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response postJson(ForceStatus status) {
new TestExecution(status).start();
return Response.status(Response.Status.OK).build();
}
}
TestExecution:
public class TestExecution extends Thread {
private ForceStatus status;
public ExamExecution(ForceStatus status) {
this.status = status;
}
@Override
public void run() {
ProtocolStatus p = new ProtocolStatus();
byte[] s = p.createResponseFrame(status.getForce());
List<Integer> executedTest = new ArrayList<>();
//Simple UDP client
UDPClient client = new UDPClient();
.
.
.
//t is a pojo which contains the data from a battery of tests
while(!executedTest.contains(t.getTestId())) {
client.send(status.getIp(), status.getPort(), s);
//TODO wait until UDPServer thread gets the response from the device
executedTest.add(t.getTestId());
nextTest = t.getNextTestId();
t = getEntity(nextTest);
}
}
}