为什么ExecutorService方法invokeAny在每次运行的程序上都处理不同数量的任务?

问题描述

看下面的代码:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

public class InvokeAny {
    public static void main(String[] args) {
        Callable<String> callableTask = () -> {
            TimeUnit.MILLISECONDS.sleep(300);
            System.out.println("Callable task's execution");
            return "Task's execution";
        };

        List<Callable<String>> callableTasks = new ArrayList<>();
        callableTasks.add(callableTask);
        callableTasks.add(callableTask);
        callableTasks.add(callableTask);

        ExecutorService executorService = Executors.newFixedThreadPool(2);
        try {
            executorService.invokeAny(callableTasks);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }

        shutdownAndAwaitTermination(executorService);
    }

    private static void shutdownAndAwaitTermination(ExecutorService pool) {
        pool.shutdown(); // Disable new tasks from being submitted
        try {
            // Wait a while for existing tasks to terminate
            if (!pool.awaitTermination(1000,TimeUnit.MILLISECONDS)) {
                pool.shutdownNow(); // Cancel currently executing tasks
                // Wait a while for tasks to respond to being cancelled
                if (!pool.awaitTermination(1000,TimeUnit.MILLISECONDS))
                    System.err.println("Pool did not terminate");
            }
        } catch (InterruptedException ie) {
            // (Re-)Cancel if current thread also interrupted
            pool.shutdownNow();
            // Preserve interrupt status
            Thread.currentThread().interrupt();
        }
    }
}

每次运行程序时,在控制台中都会得到不同的结果。

第一次运行:

Callable task's execution

第二次运行:

Callable task's execution
Callable task's execution

第三次运行:

Callable task's execution

有人可以解释一下为什么会这样吗?

在Oracle文档中,关于方法invokeAny(Collection<? extends Callable<T>> tasks)只有一句话:

执行给定的任务,返回具有以下条件的任务的结果 成功完成(即没有引发异常)(如果有)

我想了解它的工作原理。完成一项任务后,它会取消剩余的任务吗?如果可以,为什么有时我会执行2个任务?

解决方法

完成一项任务后,它会取消剩余的任务吗?

是的,这是正确的,但这并不意味着它将仅在当前任务完成后才提交/启动下一个任务,这就是并发的全部目的,它不等待上一个任务完成。一次提交任务,不要等待任务完成,同时检查是否有任务完成,是否完成,取消所有当前正在运行的任务,不提交其余任务而只返回完成的任务。>

现在,在最终取消正在运行的任务之前,它们可能已经完成了工作,或者可能没有完成(对于您而言是print语句),具体取决于每个线程获得的时间片,这取决于各种JVM和系统因素,例如在评论中指出。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...