I have a "client" EJB
that invokes 4 Asynchronous
EJB
s and should give them all 5 seconds to run. After 5 seconds the "client" EJB collects the ready results from Future
object that finished running, and returns output.
I have a problem with the "waiting" in client part. I tried to invoke future.get(5, TimeUnit.MILLISECONDS)
It seems like sometimes async EJB
s start to run after the timeout.
Is there a correct way to do it?
1) Collect Future
objects in Map
:
Map<String, Future> futureMap = new HashMap<String, Future>();
for (String userID: users) {
Future<Set<FrontPageData>> test = util.asyncGetData(userID);
futureMap.put(serviceID, test);
}
return futureMap;
2) Then I get output with timeout from Future
objects
final long now = Calendar.getInstance().getTimeInMillis();
final long end = now + TimeUnit.SECONDS.toMillis(5)
Map<String, Object> output = new HashMap<String, Object>();
Object data;
for (String userID: futureMap.keySet()) {
Future future= futureMap.get(userID);
try {
//check how much time left till the end
long timeout = end - Calendar.getInstance().getTimeInMillis();
data = future.get(timeout, TimeUnit.MILLISECONDS);
output.put(userID, data);
} catch (Exception e) {//write to logs
}
}
return output;
}
thank you
I don't think your client should be aware of the details whether the async code still has to be scheduled or whether it has been running for those 5 seconds.
All your client should be concerned about is the total waiting time. Since no system has unlimited resources, there can't be any guarantee that the async code starts running right away.
If you want to limit the actual execution time to 5 seconds, the only realistic way is to do this in the bean that executes the code.
p.s.
Not related to your question, but why do this weird calculation for timeout? You now do "now + 5 seconds - now", which is 5 seconds again.
And, if you iterate over a Map and need both the value and key, you can iterate over the entrySet, instead of over the key set and then doing a
get()
for each key.