关闭执行程序服务(等待终止时)和等待取消提交的任务(使用提交的期货)之间的比较

Comparison between shutting down an executor service (while awaiting termination) and wait cancellation of submitted tasks (using submit's futures)

因此 Oracle itself 提出的关闭 ExecutorService 的最佳实践如下:

@PreDestroy
public void cleanUp(){
        executorService.shutdown();

        try {
            if (executorService.awaitTermination(TIMEOUT, TimeUnit.MILLISECONDS)) {
                executorService.shutdownNow();
            }
        } catch (InterruptedException e) {
            executorService.shutdownNow();
        }
}

这也将负责取消任何待处理的任务。我想知道 何时 上面的代码片段比以下代码片段更受欢迎:

private List<Future> tasks = Collections.EMPTY_LIST;

public void doStuff(){
    for (Service service : services) {
            Future<?> future = executorService.submit(()->service.update(args));
            tasks.add(task);
    }
}

@PreDestroy
public void cleanUp() {

    for (Future task : tasks) {
        task.cancel(false);
    }
}

后者将允许 运行 任务在不中断的情况下完成 (tasks.cancel(false))。在这种方法中没有超时,因此任务中的无限循环会阻止应用程序停止。此外,我们还剩下一个 运行 executors 服务:但是如果确定在取消的任务完成后没有其他任务可以提交,我们真的应该关心这个吗?

我最感兴趣的是在要等待 termination/completion 作业任务后再进行实际关闭的情况下,什么是最佳实践。为什么我们实际上关心执行程序服务本身的关闭?

恕我直言,拥有一个在应用程序关闭时可以取消的期货列表是一个更简洁的解决方案,因为可能 select 哪些要被中断,哪些要等待完成。

非常欢迎对此有任何更详尽的见解。

这些都是 Spring bean 的一部分,正如您可以从用于将 cleanUp 方法指定为用于清理任务的关闭挂钩的 @PotsDestroy 注释中推断的那样执行者服务。

在建议的解决方案中,wait 应该在 shutdownNow() 方法调用之后调用。

An unused ExecutorService should be shut down to allow reclamation of its resources.

shutdownNow():-

  • 将 运行 状态转换为停止
  • 如果启动则中断 worker
  • 清空队列 - 删除所有线程

Future.cancel(假):-

  • 不中断 运行ning 任务
  • 如果任务已经完成,则取消尝试将失败,有 已经取消,或无法为其他人取消 原因。您可能需要额外的逻辑来处理不同的 场景。 shutdownNow() 已经处理了这些情况。

简短描述和推荐:-

  • 实际上,List对象本身不是线程安全的

  • 单例 bean 是无状态的。它不应该保持状态 在 class 级别。即使您将其声明为原型 bean,它也是 维护列表(列表不是线程安全的)不是一个好习惯 期货。

在内部,诸如 ThreadPoolExecutor、ScheduledThreadPoolExecutor 等执行器服务实现 class 负责处理所有线程安全问题。它使用 BlockingQueue 来克服线程安全问题。此外,它相应地处理异常和不同的状态。您可能需要了解所有内部结构(即引擎盖下发生的事情)才能提出一个好的自定义解决方案。

最简单和最好的方法是使用执行程序服务实现中可用的标准实现(ThreadPoolExecutor、ScheduledThreadPoolExecutor 等) 以避免任何不利影响(即内存泄漏、线程安全问题)。