This question already has answers here:
is invokeAll() a blocking call in java 7
(3 answers)
Closed 3 years ago.
It is said invokeAll is used when we want to wait for completion of all tasks as compared to submit or execute which does not wait.
What do we mean by completion of tasks. Does it mean that parent thread which spawns all other thread get stuck in that point until all the thread returns?
See javadoc
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException
Does it mean that parent thread which spawns all other thread get stuck in that point until all the thread returns?
Yes you are right ! see below code this is implementation of invokeAll from AbstractExecutorService.java (oracle JDK8). More importantly you need to notice For loop there. We check if (!f.isDone()) , that means if task is not done (complete) go inside loop and call f.get(), which is blocking call. Effectively you caller of invokeAll is blocked till all tasks are not completed.
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException {
if (tasks == null)
throw new NullPointerException();
ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
boolean done = false;
try {
for (Callable<T> t : tasks) {
RunnableFuture<T> f = newTaskFor(t);
futures.add(f);
execute(f);
}
for (int i = 0, size = futures.size(); i < size; i++) {
Future<T> f = futures.get(i);
if (!f.isDone()) {
try {
f.get();
} catch (CancellationException ignore) {
} catch (ExecutionException ignore) {
}
}
}
done = true;
return futures;
} finally {
if (!done)
for (int i = 0, size = futures.size(); i < size; i++)
futures.get(i).cancel(true);
}
}
Related
ExecutorService executorService = Executors.newSingleThreadExecutor();
Set<Callable<String>> callables = new HashSet<Callable<String>>();
callables.add(new Callable<String>() {
public String call() throws Exception {
return "Task 1";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
return "Task 2";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
return "Task 3";
}
});
List<Future<String>> futures = executorService.invokeAll(callables);
for(Future<String> future : futures){
System.out.println("future.get = " + future.get());
}
For this code piece. My question is "is invokeAll() a blocking call "?
I mean, when code ran to invokeAll() line, are we bloking there to wait for all result been generated?
Executes the given tasks, returning a list of Futures holding their
status and results when all complete. Future.isDone() is true for each
element of the returned list. Note that a completed task could have
terminated either normally or by throwing an exception. The results of
this method are undefined if the given collection is modified while
this operation is in progress.
Futures can only be done when execution is finished, therefore this method can only return when the tasks have been executed.
That it can throw an InterruptedException is also indicative of a blocking action.
Looking at the implementation of invokeAll in java.util.concurrent.AbstractExecutorService (comment inline):
// from OpenJDK source; GPL-2.0-with-classpath-exception
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException {
if (tasks == null)
throw new NullPointerException();
ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
boolean done = false;
try {
for (Callable<T> t : tasks) {
RunnableFuture<T> f = newTaskFor(t);
futures.add(f);
execute(f);
}
for (int i = 0, size = futures.size(); i < size; i++) {
Future<T> f = futures.get(i);
if (!f.isDone()) {
try {
f.get(); // <== *** BLOCKS HERE ***
} catch (CancellationException ignore) {
} catch (ExecutionException ignore) {
}
}
}
done = true;
return futures;
} finally {
if (!done)
for (int i = 0, size = futures.size(); i < size; i++)
futures.get(i).cancel(true);
}
}
In fact, looking at a reference implementation is what you generally should do in these cases when the Javadoc-Specese appears to be difficult to decipher. (with the caveat in mind that some implementation details are not part of the spec.)
You mean if the parent thread will wait for all the thread created using your ExecutorService invocation? Then answer is yes, parent thread will wait and once all threads are finished you will get the list of Futures object which will hold the result of each thread execution.
See below from ExecutorService.invokeAll()
Executes the given tasks, returning a list of Futures holding their
status and results when all complete.
InvokeAll method blocks till all the tasks are completed and list of futures are returned,
Solution:
If we don't want this to happen and continue with execution of program ,we can Loop through the tasks and pass it to Submit method of ExecutorService and add it to the List of Future Objects
ExecutorService es=Executors.newFixedThreadPool(4);
List<SampleClassimplementingCallable<String>> tasks=new ArrayList<>();
List<Future<String>> futures=new ArrayList<>();
for(SampleClassimplementingCallable<String> s:tasks)
{
//This Won't Block the Calling Thread and We will get the list of futures
futures.add(es.submit(s));
}
However, When the Futures are retrieved from the list and get method is called on indivual future object ,then the thread is blocked.
I am struggling with a use case where one of the tasks submitted to invokeall() throws CancellationException forcing program NOT to terminate. How can make sure this program will terminate properly in case of CancellationException ?
How I am finding out my program not terminated clean? I am using netbeans and shows progress bar at bottom right if program doesn't terminate.
Here is code:
int poolSize = Runtime.getRuntime().availableProcessors();
ExecutorService pool = Executors.newFixedThreadPool(poolSize);
Set<Callable<Object>> tasksSet = new HashSet<>();
tasksSet.add(new Task1());
tasksSet.add(new Task2());
tasksSet.add(new Task3());
List<Future<TrendLineStatisticsVO>> resultSet = pool.invokeAll(tasksSet, 1, TimeUnit.MINUTES);
for (Future<Object> future : resultSet) {
Object result;
try {
result = future.get(5, TimeUnit.SECONDS);
} catch (InterruptedException ex) {
ex.printStackTrace();
Logger.getLogger(CallableDemo.class.getName()).log(Level.SEVERE, null, ex);
} catch (ExecutionException ex) {
ex.printStackTrace();
Logger.getLogger(CallableDemo.class.getName()).log(Level.SEVERE, null, ex);
} catch (TimeoutException ex) {
ex.printStackTrace();
Logger.getLogger(CallableDemo.class.getName()).log(Level.SEVERE, null, ex);
}
}
pool.shutdown();
And Task1 code:
public class Task1 implements Callable<Object> {
#Override
public Object call() throws Exception {
//This for sure takes days to complete, so should through Cancellation exception because timeout on invokeall set to 1 minute
long val = 0;
for (long i = 0; i < Long.MAX_VALUE - 5000; i++) {
val += i;
}
return "Sucessfull Task1 object...";
}
}
Task2 and Task3 code also same except these two classes use Integer.MAX_VALUE in for loop check.
There are two issues:
1)
Per the Javadoc:
tasks that have not completed are cancelled.
So you will have to code your Task to be responsive to interruption. What is happening in the background is similar to future.cancel(true) if the tasks don't complete in the time specified, the true in the argument says to interrupt() the thread running the task. Like I mentioned, your tasks will have to look out for interruption. Something similar to:
#Override
public Object call() throws Exception {
//This for sure takes days to complete, so should through Cancellation exception because timeout on invokeall set to 1 minute
long val = 0;
for (long i = 0; i < Long.MAX_VALUE - 5000; i++) {
if(Thread.interruped()){
throw new RuntimeException("Did not complete in time: " + i);
}
val += i;
}
return "Sucessfull Task1 object...";
}
How I am finding out my program not terminated clean? I am using netbeans and shows progress bar at bottom right if program doesn't terminate.
Without my update above the program will never end as the thread pool is still running. shutdown will do nothing as the tasks haven't completed (event with cancel).
2)
A task that is cancelled, by definition, did not complete (or even start) so invoking get on the Future will fail quickly. You could ask the future if it's cancelled Future#isCancelled.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to know if other threads have finished?
I have a threadpool that executes threads for me, how can I tell when ALL the threads I've passed it are done?
For example:
main.java
for (int i = 0; i < objectArray.length; i++) {
threadPool.submit(new ThreadHandler(objectArray[i], i));
Thread.sleep(500);
}
ThreadHandler.java
public class ThreadHandler implements Runnable {
protected SuperHandler HandlerSH;
protected int threadNum;
public ThreadHandler(SuperHandler superH, int threadNum) {
this.threadNum = threadNum;
this.HandlerSH = superH;
}
public void run() {
//do all methods here
}
Would I just put something into the run() section to set a boolean or something? Would I make an array of boolean to check when they're all done?
Thanks.
When you submit a job into a thread pool, it returns a Future instance. You can call Future.get() to see if the job has finished. This is effectively similar to a join on the tasks running in a thread pool.
You can also call threadPool.awaitTermination(...) if the thread-pool has been shutdown and you want to wait for all of the tasks have finished.
Often when I am submitting a number of jobs into a thread pool, I record their futures in a list:
List<Future<?>> futures = new ArrayList<Future<?>>();
for (int i = 0; i < objectArray.length; i++) {
futures.add(threadPool.submit(new ThreadHandler(objectArray[i], i)));
}
// if we are done submitting, we shutdown
threadPool.shutdown();
// now we can get from the future list or awaitTermination
for (Future<?> future : futures) {
// this throws an exception if your job threw an exception
future.get();
}
I'm trying to implement a sample application to test Callable and ExecutorService interfaces.
In my app I have declared:
ExecutorService exSvc = Executors.newSingleThreadExecutor();
Then:
Future<Integer> test = exSvc.submit(
new Callable<Integer>() {
public Integer call() {
for(int i = 0; i < 1000; i++){
System.out.println(i);
}
return 1;
}
});
Now I'm trying to stop the process before it terminate, I'm using exSvc.shutdownNow() but it doesn't work.
To stop gracefully a classical Thread I usually use some kind of condition variable. Which is a common approach to follow with ExecutorService?
Future.cancel(true) and ExecutorService.shutdownNow() use thread interruption. As long as you don't make uninterruptable blocking calls in your task, all you need is to handle interrupted condition correctly, something like this:
for(int i = 0; i < 1000; i++){
// Uses isInterrupted() to keep interrupted status set
if (Thread.currentThread().isInterrupted()) {
// Cannot use InterruptedException since it's checked
throw new RuntimeException();
}
System.out.println(i);
}
If you make uninterruptable blocking calls (such as network IO), things become more complex, you need to interrupt them manually somehow, for example, by closing the underlying sockets.
This is how I'd do it with a FixedThreadPool, hope it's of some help.
ExecutorService pool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
List<Future<Void>> results = new ArrayList<>();
for (int i = 0; i < numberOfJobs; i++) {
MyCallableJob job = new MyCallableJob (...);
results.add(pool.submit(job));
}
for (Future<Void> result : results) {
try { result.get(); }
catch (InterruptedException | ExecutionException ignorable) { }
}
pool.shutdown();
I'd like to execute multiple callables parallel. But it seems that the ExecutorService always waits until all callables are finnished.
I've tried the following:
final int nThreads = 10;
ExecutorService executorService = Executors.newFixedThreadPool(nThreads);
List<PrimeCallable> tasks = new ArrayList<PrimeCallable>();
for(int i = 0; i < nThreads; i++) {
tasks.add(new PrimeCallable(0, i * 100 + 100, "thread" + i));
}
try {
for(Future<List<Integer>> result : executorService.invokeAll(tasks)) {
List<Integer> integers = result.get();
for(Integer i : integers){
System.out.println(i);
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Now, the for loop is called when all callables in the executorService are finnished. As far as I know, there is no executorService.isParallel setter ;-).
What would be the right approach to let callables run parallel?
Thanks for your hints!
The javadocs for invokeAll says;
Executes the given tasks, returning a
list of Futures holding their status
and results when all complete. Future.isDone() is true for each element of the returned list.
So invokeAll blocks until each task in the collection is complete.
Executor service runs all your callables in parallel. All it does is , it waits for all parallel tasks to complete before it moves on. So its not like where all the tasks are run in serial.
It sounds like part of what you want is lazy execution - you don't want to have to make a copy of the structure in memory before extracting results.
I would treat this as an iteration + transformation problem. First, define an iterator over your input, such that each call to next() returns a Callable that will produce the next value in your series.
The transform stage is to apply a parallel or concurrent evaluation of those Callables, something like this (not tested):
public class ConcurrentTransform
{
private final ExecutorService executor;
private final int maxBuffer;
public ConcurrentTransform(ExecutorService executor, int maxWorkBuffer) {
this.executor = executor;
this.maxBuffer = Math.max(1, maxWorkBuffer);
}
public <T> Iterator<T> apply(final Iterator<Callable<T>> input) {
// track submitted work
final BlockingQueue<Future<T>> submitted = new LinkedBlockingQueue<Future<T>>();
// submit first N tasks
for (int i=0; i<maxBuffer && input.hasNext(); i++) {
Callable<T> task = input.next();
Future<T> future = executor.submit(task);
submitted.add(future);
}
return new Iterator<T>(){
#Override
public synchronized boolean hasNext() {
return !submitted.isEmpty();
}
#Override
public T next() {
Future<T> result;
synchronized (this) {
result = submitted.poll();
if (input.hasNext()) {
submitted.add(executor.submit(input.next()));
}
}
if (result != null) {
try {
return result.get(); // blocking
} catch (Exception e) {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
} else {
throw new RuntimeException(e);
}
}
} else {
throw new NoSuchElementException();
}
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}};
}
}
After calling apply(...), you'd iterate over the resulting values, which under the covers would be executing the Callable objects in parallel and returning results in the same order as they were input. Some refinements would be to allow an optional timeout for the blocking result.get() call, or to manage the thread pool within the transform itself.
If you want to view results as they happen, use the ExecutorCompletionService.