We can invoke easy in the same time a set of threads. Here's a sample:
Collection<Callable<Product>> callableTasks = new ArrayList<>();
for (int i = 0; i < 5; i++)
callableTasks.add(new MyCallableTask(i));
List<Future<Product>> results = defaultExecutor.invokeAll(callableTasks);
for (Future<Product> f : results)
f.get();
The invokeAll method of the managed executor service starts at the same time as all objects in the list as multiple threads. Then, each thread will expire once the get method starts returning a result; in this case, a Product object.