Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does invokeAny cancel all the threads in a Thread pool or only callables?

I'm creating a fixed size ExecutorService, which is going to be accessed from multiple threads.

ExecutorService executorService = Executors.newFixedThreadPool(2);

Then I'm calling invokeAny from two different threads using the same ExecutorService.

executorService.invokeAny(listCallables);

So there is a possibility that in the thread pool there can be multiple tasks called from different threads.

As per the invokeAny documentation:

Upon normal or exceptional return, tasks that have not completed are cancelled.

My question is, upon successful return of invokeAny, will it cancel all the threads which are in the thread pool or will it cancel only the tasks which are called in separate threads?

like image 602
Arsen Davtyan Avatar asked Oct 17 '25 03:10

Arsen Davtyan


2 Answers

Upon normal return of invokeAny, the threadpool will cancel all uncompleted tasks. You can refer to my example:

package com.pechen;

import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

public class SleepSecondsCallable implements Callable<String> {
    private String name;

    private int seconds;

    public SleepSecondsCallable(String name, int seconds) {
        this.name = name;
        this.seconds = seconds;
    }

    public String call() throws Exception {
        System.out.println(name + ",begin to execute");

        try {
            TimeUnit.SECONDS.sleep(seconds);
        } catch (InterruptedException e) {
            System.out.println(name + " was disturbed during sleeping.");
            e.printStackTrace();
            return name + ",fails to execute";
        }

        return name + ",success to execute";
    }

}

The main class:

package com.pechen;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class Main {

    public static void main(String[] args) throws InterruptedException, ExecutionException {
            ExecutorService executorService = Executors.newFixedThreadPool(3);  

            List<Callable<String>> tasks = new ArrayList<Callable<String>>();  

            tasks.add(new SleepSecondsCallable("t1", 2));  
            tasks.add(new SleepSecondsCallable("t2", 1));  

            String result = executorService.invokeAny(tasks);  
            System.out.println(result);  
            executorService.shutdown();  

    }

}

The output:

t1,begin to execute
t2,begin to execute
t2,success to execute
t1 was disturbed during sleeping.
java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at java.lang.Thread.sleep(Unknown Source)
    at java.util.concurrent.TimeUnit.sleep(Unknown Source)
    at com.pechen.SleepSecondsCallable.call(SleepSecondsCallable.java:20)
    at com.pechen.SleepSecondsCallable.call(SleepSecondsCallable.java:1)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

You can see, specify thread t2 to sleep for 1 second and t1 for 2. When t2 successfully returns, theadpool interupts the execution of t1.

like image 179
Dave Pateral Avatar answered Oct 18 '25 17:10

Dave Pateral


From invokeAny implementation in Java Sources:

try {
    ....
} finally {
    for (Future<T> f : futures)
        f.cancel(true);
} 

This means invokeAny cancels only the callable-s which has been submitted to it.

like image 20
Arsen Davtyan Avatar answered Oct 18 '25 16:10

Arsen Davtyan