An alternative would be the use of Executorservice
Basic Example:
Rpcresult.class:
public class RpcResult {
private int clientId;
private String response;
// getters and setters...
}
Rpcexecutor.class:
public class RpcExecutor implements Callable<RpcResult>{
private int clientId;
public RpcExecutor(int clientId) {
this.clientId = clientId;
}
public RpcResult call() throws Exception {
RpcResult result = new RpcResult();
result.setClientId(clientId);
result.setResponse("Resposta do cliente: " + clientId);
return result;
}
}
Execution:
ExecutorService executor = Executors.newFixedThreadPool(3);
List<Callable<RpcResult>> list = new ArrayList<Callable<RpcResult>>();
for (int i = 1; i <= 3; i++) {
list.add(new RpcExecutor(i));
}
// 3 segundos de timeout
List<Future<RpcResult>> future = executor.invokeAll(list, 3L, TimeUnit.SECONDS);
for(Future<RpcResult> f : future) {
try {
if (!f.isCancelled()) {
RpcResult result = f.get();
System.out.println(result.getClientId());
System.out.println(result.getResponse());
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
};
executor.shutdown();
To simulate the timeout of a client just add a Thread.Sleep() in the call() method of the Rpcexecutor class:
public RpcResult call() throws Exception {
if (clientId == 2)
Thread.sleep(15000);
RpcResult result = new RpcResult();
result.setClientId(clientId);
result.setResponse("Resposta do cliente: " + clientId);
return result;
}
EDIT
According to the new information related to the current project structure, this solution would not have scalability.
If you keep in mind that your application will never have many users, ok, go for the simplest solution. Now, if your application needs to scale, this could be one of the alternatives(simplified model):
Thanks for the answer. I forgot to say in the question that it is Java7. The Future stream I think is java 8. The biggest problem I have is not having access to the source code of the call() method. But I can use executor logic to call. invokeall can I set timeout ? By the way another issue that disturbs me, We are talking about a code of a Servlet, create N threads for each client can not create performance problem?
– user2989745
@user2989745 1 - Regarding the stream, just use a "for" in Java7, edit the answer. 2 - You can set the timeout of invokeAll. 3 - Since it is a web application, this solution is not very scalable. Suppose you have to consult 30 clients and you start one thread per client (30 threads per requests), then if your application gets 100 requests, it would be 100 * 30 threads open. I would go to an asynchronous solution requesting these queries for another application and the client could receive the reply by websocket...
– Tom Melo
Thank you! Yes I thought so, I wanted another opinion. Can you deepen your structure ? What would you gain from the asynchronous ? The action is triggered by a click on a button on the front end. I don’t know how to better control RPC response time....
– user2989745
@user2989745 What you get with an asynchronous solution is that you don’t secure a request on your server waiting for answers from third-party services that you don’t know how long they will respond to. I updated my answer to give you an idea of what it would be like.
– Tom Melo
Yeah, I see where the asynchronous can help. I get your idea, and it sounds like a good idea. I will study Websockets better, to see how it fits. But yes, interesting idea, thanks for the explanation.
– user2989745