I am in the situation where I have a collection of objects and every object has to run an expensive method that takes about 5-10 seconds to complete.
How can I run all methods in parallel and check the status periodically?
I tried to use the @Async annotation with a Future response, but nothing changed.
public static void populate(String marketId) {
//irrelevant code removed
List<Company> companies = mongo().find(new Query(c), Company.class);
List<Future> futures = new ArrayList<Future>();
for(Company comp : companies) {
futures.add(comp.updateData(market));
}
}
@Async
public Future<Boolean> updateData(Market market) {
//do my slow logic here
return new AsyncResult(false);
}
Is the ThreadPoolTaskExecutor the way to go?
I'm a bit confused as to the reasons you use AsyncResult (and which implementation... ejb?).
If I'm not mistaken, it will not work that way, as (from what I know) AsyncResult is connected to the bean and @Asyncronous annotation making the response from a specific bean method assyncronous. But if used inside an object, it would be effectively sequential.
What you need here is a normal Future. If so, you need to actually run these futures in an executor and than wait until they finish by calling future.get().
A nice tutorial on that you can find here:
http://java.dzone.com/articles/javautilconcurrentfuture
You can also look into Akka. Actor model is my personal favourite, as you can simply spawn a bunch of workers, tell them what to do, and let them let you know once they're done with their job. Still it might be an overkill if you only have a simple task at hand, depends on your style.
ExecutorService pool = Executors.newFixedThreadPool(10);
public static void populate(String marketId) {
//irrelevant code removed
List<Company> companies = mongo().find(new Query(c), Company.class);
List<Future> futures = new ArrayList<Future>();
for(Company comp : companies) {
futures.add(comp.updateData(market));
}
for(Future future: futures) {
future.get()
}
}
public Future<Boolean> updateData(Market market) {
return pool.submit(new Callable<Boolean>() {
@Override
public Void call() throws Exception {
//do your slow stuff here;
return false;
}
})
}
of cause this makes sense if you need to get some actual return from those futures. If they're void, and you just need a thread to run some side-effects somewhere else, than there's no point in doing it that way, and you can simply use runnables and executor. Something similar to this:
wait until all threads finish their work in java