kosa
kosa

Reputation: 66637

ExecutorService invokeall threadpool issue

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.

Upvotes: 0

Views: 1164

Answers (1)

John Vint
John Vint

Reputation: 40256

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.

Upvotes: 1

Related Questions