java - 关闭执行程序服务(等待终止时)与等待取消已提交任务(使用 Submit 的 future)之间的比较

标签 java spring executorservice

因此 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))。在这种方法中,没有超时,因此任务中的无限循环将阻止应用程序停止。此外,我们还剩下一个仍在运行的执行程序服务:但是,如果确定在已取消的任务完成后无法提交其他任务,我们真的应该关心这个吗?

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

恕我直言,拥有一份在应用程序关闭时取消的 future 列表是一种更简洁的解决方案,因为人们可以选择哪些要中断,哪些要等待完成。

对此的任何更详细的见解都非常受欢迎。

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

最佳答案

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

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

shutdownNow():-

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

Future.cancel(假):-

  • 不中断正在运行的任务
  • 如果任务已经完成,则取消尝试将会失败 已经被取消,或者无法取消其他一些 原因。您可能需要额外的逻辑来处理不同的 场景。 shutdownNow() 已经可以处理这些场景。

简短描述和建议:-

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

  • 单例 bean 是无状态的。它不应该维持状态 在类(class)层面。即使你将其声明为原型(prototype) bean,它也是 维护 List 不是一个好习惯(List 不是线程安全的) future 。

在内部,执行器服务实现类(例如 ThreadPoolExecutor、ScheduledThreadPoolExecutor 等)负责处理所有线程安全问题。它使用BlockingQueue来克服线程安全问题。此外,它还相应地处理异常和不同的状态。您可能需要了解所有内部结构(即幕后发生的情况)才能提出良好的定制解决方案。

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

关于java - 关闭执行程序服务(等待终止时)与等待取消已提交任务(使用 Submit 的 future)之间的比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52163885/

相关文章:

java - 如何在ThreadFactory中初始化ThreadLocal变量?

java - 在 ExecutorService 线程中运行 Http Server 或无限持续时间任务是否合适

java - 等待 JavaFX 应用程序线程完成事件处理?

spring - 使用问题: Spring AOP vs. AspectJ编织

java.lang.NoClassDefFoundError : Could not initialize class org. apache.cxf.jaxrs.provider.ProviderFactory

java - 未找到 Spring-data-elasticsearch Maven 依赖项

java - 如何解决错误 "The following classes could not be excluded because they are not auto-configuration classes"?

java - 尝试运行 OpenCV 教程 2 - 混合处理演示

java - 使用 Marshaller 将 Java 对象转换为 Json

java - 在本地模式下运行 Apache Storm 连接错误