invokeAny 是取消线程池中的所有线程还是仅取消可调用线程?

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

我正在创建一个固定大小的 ExecutorService,它将被多个线程访问。

ExecutorService executorService = Executors.newFixedThreadPool(2);

然后我使用相同的 ExecutorService 从两个不同的线程调用 invokeAny

executorService.invokeAny(listCallables);

所以有可能在线程池中可以有多个任务从不同的线程调用。

根据 invokeAny 文档:

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

我的问题是,在 invokeAny 的 return 成功后,它会取消线程池中的所有线程还是只取消在单独线程中调用的任务?

invokeAny 的正常 return 时,线程池将取消所有未完成的任务。你可以参考我的例子:

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";
    }

}

主要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();  

    }

}

输出:

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)

可以看到,指定线程t2休眠1秒,t1休眠2秒。当t2成功returns时,adpool中断执行t1.

来自 invokeAny 在 Java 中的实施来源:

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

这意味着invokeAny只取消已经提交给它的callable-s。