java - 何时使用 ScheduledThreadPoolExecutor 的“removeOnCancel”策略
问题描述
Java 的 JavadocsScheduledThreadPoolExecutor
声明如下:
当提交的任务在运行之前被取消时,执行被抑制。默认情况下,此类取消的任务不会自动从工作队列中删除,直到其延迟结束。虽然这可以进行进一步的检查和监控,但它也可能导致取消任务的无限保留。为避免这种情况,请设置
setRemoveOnCancelPolicy(boolean)
为 true,这会导致任务在取消时立即从工作队列中删除。
我将其解释为
- 默认情况下,如果您在“计划”任务时尝试取消
ScheduledFuture
返回ScheduledThreadPoolExecutor
的任务,则该任务将不会真正从队列中删除,直到我们计划的持续时间完全过去。 - 通过将
ScheduledThreadPoolExecutor
'设置removeOnCancelPolicy
为 true,我们会立即从工作队列中删除任务,而不是等待预定的持续时间,直到任务从工作队列中取出。
问题
removeOnCancelPolicy
将 设置为 true有什么后果吗?
我正在考虑这样做,以确保工作队列不会变得太大并占用太多内存,但我对为什么默认情况下不启用此策略感到困惑。
解决方案
@hc_dev 的答案很好,并解释了设置removeOnCancelPolicy
为 true 的许多后果,但是将该值设置为 true 的另一个后果 - 您的阻塞队列的并发性ScheduledExecutorService
可能会受到影响。
默认情况下,工厂方法ScheduledExecutorService
创建的使用 a作为其工作队列。这个工作队列由一个包含在其中的数组组成,由一个锁保护。这意味着当一个线程正在从 执行任务时,其他线程将不得不等待,以便在每次取消任务时从工作队列中推送或弹出任何内容。因此,设置 removeOnCancelPolicy 将引发阻塞队列上的锁争用并降低队列的并发性。Executors.newScheduledThreadPool
ScheduledThreadPoolExecutor.DelayedWorkQueue
remove
ScheduledThreadPoolExecutor.DelayedWorkQueue
JavadocsScheduledThreadPoolExecutor.DelayedWorkQueue
对它的 remove 方法的性能有这样的说法:
DelayedWorkQueue 是基于类似于 DelayQueue 和 PriorityQueue 中的基于堆的数据结构,除了每个 ScheduledFutureTask 还将其索引记录到堆数组中。这消除了在取消时查找任务的需要,大大加快了删除速度(从 O(n) 降低到 O(log n)),并减少了在清除之前等待元素上升到顶部而可能发生的垃圾保留。
因此,该remove
方法的性能非常好,并且可以很好地扩展队列中的许多条目,但要记住这一点。
推荐阅读
- optimization - Google 优化报告不显示转化
- ubuntu - 使用“代码”在匹配的 CWD 中打开 VS 代码?
- oracle-data-integrator - 在 ODI 12c 元数据存储库的 SNP_SESSIONS 表中,列 NB_ROW、NB_INS、NB_UPD、NB_DEL 均为 0
- java - 如何修复 POIXMLException 说没有任何内容类型规则
- vb.net - 删除表记录,但不重复
- c++ - 从 QFontDatabase::addApplicationFont 获取字体系列名称
- reactjs - 我正在尝试使用 React js 将对象列表中的 ID 映射到新列表中
- python - 如何在 python 中更快地从 s3 读取和处理多个文件?
- json - 如何使用 Postman 映射 Elasticsearch 中的列(非法参数异常)
- php - 如何修复jquery错误意外令牌错误