首页 > 解决方案 > 何时使用 ScheduledThreadPoolExecutor 的“removeOnCancel”策略

问题描述

Java 的 JavadocsScheduledThreadPoolExecutor声明如下:

当提交的任务在运行之前被取消时,执行被抑制。默认情况下,此类取消的任务不会自动从工作队列中删除,直到其延迟结束。虽然这可以进行进一步的检查和监控,但它也可能导致取消任务的无限保留。为避免这种情况,请设置setRemoveOnCancelPolicy(boolean)为 true,这会导致任务在取消时立即从工作队列中删除。

我将其解释为

问题

removeOnCancelPolicy将 设置为 true有什么后果吗?

我正在考虑这样做,以确保工作队列不会变得太大并占用太多内存,但我对为什么默认情况下不启用此策略感到困惑。

标签: javathreadpoolexecutorscheduledexecutorservice

解决方案


@hc_dev 的答案很好,并解释了设置removeOnCancelPolicy为 true 的许多后果,但是将该值设置为 true 的另一个后果 - 您的阻塞队列的并发性ScheduledExecutorService可能会受到影响。

默认情况下,工厂方法ScheduledExecutorService创建的使用 a作为其工作队列。这个工作队列由一个包含在其中的数组组成,由一个锁保护。这意味着当一个线程正在从 执行任务时,其他线程将不得不等待,以便在每次取消任务时从工作队列中推送或弹出任何内容。因此,设置 removeOnCancelPolicy 将引发阻塞队列上的锁争用并降低队列的并发性。Executors.newScheduledThreadPoolScheduledThreadPoolExecutor.DelayedWorkQueueremoveScheduledThreadPoolExecutor.DelayedWorkQueue

JavadocsScheduledThreadPoolExecutor.DelayedWorkQueue对它的 remove 方法的性能有这样的说法:

DelayedWorkQueue 是基于类似于 DelayQueue 和 PriorityQueue 中的基于堆的数据结构,除了每个 ScheduledFutureTask 还将其索引记录到堆数组中。这消除了在取消时查找任务的需要,大大加快了删除速度(从 O(n) 降低到 O(log n)),并减少了在清除之前等待元素上升到顶部而可能发生的垃圾保留。

因此,该remove方法的性能非常好,并且可以很好地扩展队列中的许多条目,但要记住这一点。


推荐阅读