views:

51

answers:

2

I need to call a number of methods in parallel and wait for results. Each relies on different resources, so they may return at different times. I need to wait until I receive all results or time out after a certain amount of time.

I could just spawn threads with a reference to a shared object via a method call, but is there a better, more groovy way to do this?

Current Implementation:

Executors exec = Executors.newFixedThreadPool(10);

for (obj in objects) {
            def method = {
                def result = new ResultObject(a: obj, b: obj.callSomeMethod())
                result
            } as Callable<ResultObject>

            callables << method
        }

        List<Future<ResultObject>> results = exec.invokeAll(callables)

        for (result in results) {
            try{
                 def searchResult = result.get()
                 println 'result retrieved'
            }  catch (Exception e)
            {
                println 'exception'
                e.printStackTrace()
            }
        }
}
+2  A: 

AbstractExecutorService.invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)

The groovy part would be using closures as Callable

Michael Borgwardt
Exactly what I needed.
Stefan Kendall
Any idea why I see only "exception" and no stack trace, or why methods that succeed normally throw exceptions?
Stefan Kendall
@Stefan: No, but things to try would be debugging into the catch block, or printing the exception object itself to see its type and message.
Michael Borgwardt
+5  A: 

A Groovier solution is to use GPars - a concurrency library written in Groovy.

import static groovyx.gpars.GParsExecutorsPool.withPool

withPool {
    def callable = {obj -> new ResultObject(a: obj, b: obj.callSomeMethod())}.async()
    List<ResultObject> results = objects.collect(callable)*.get()
}
Don