【问题标题】:Why ExecutorService method invokeAny() handles different amount of tasks on every program run?为什么 ExecutorService 方法 invokeAny() 在每个程序运行时处理不同数量的任务?
【发布时间】:2020-10-08 13:12:46
【问题描述】:

看看这段代码:

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&lt;? extends Callable&lt;T&gt;&gt; tasks) 的短语:

执行给定的任务,返回一个任务的结果 成功完成(即没有抛出异常),如果有的话 做。

我想了解它是如何工作的。它是否会在完成一项后取消剩余的任务?如果是这样,为什么有时我会执行 2 个任务?

【问题讨论】:

  • 您创建了一个带有2 线程的Executors.newFixedThreadPool()。所以我假设有 2 个任务被提交,有时它们可​​能同时完成(或不完成),让你得到这个结果。并发取决于可能不同的因素。例如。 JVM 正在做什么以及 你的 计算机在后台做什么。这样一来,一项任务可能会比另一项更快或更慢地完成

标签: java multithreading executorservice java.util.concurrent


【解决方案1】:

是否会在完成一项后取消剩余的任务?

是的,没错,但这并不意味着它只有在当前任务完成后才会提交/启动下一个任务,这就是并发的全部意义,它不会等待上一个任务完成。一个个提交任务,不要等待它们完成,同时检查是否有任务完成,如果完成了,取消所有当前正在运行的任务,不提交剩余的任务,只返回完成的任务。

现在,在最终取消正在运行的任务之前,它们可能已经完成了工作,也可能没有,在您的情况下,打印语句,取决于每个线程获得的时间片,这取决于各种 JVM 和系统因素,如在评论中指出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-16
    • 2017-03-18
    • 2017-12-30
    • 1970-01-01
    • 2014-12-06
    • 1970-01-01
    • 2015-10-24
    相关资源
    最近更新 更多