如何解决Caffeine 结合了调度器和执行器服务
我在以下配置中使用咖啡因:
Cache<String,String> cache = caffeine.newBuilder()
.executor(newWorkStealingPool(15))
.scheduler(createScheduler())
.expireAfterWrite(10,TimeUnit.SECONDS)
.maximumSize(MAXIMUM_CACHE_SIZE)
.removalListener(this::onRemoval)
.build();
private Scheduler createScheduler() {
return forscheduledexecutorservice(newSingleThreadScheduledExecutor());
}
我是否正确地假设 onRemoval
方法将在 newWorkStealingPool(15)
ForkJoinPool 上执行,并且只会调用调度程序来查找需要驱逐的过期条目?
意味着它会像这样:
我没有找到解释这种行为的文档,所以我在这里问
Tnx
解决方法
您的假设很接近,只是在实践中稍微优化了一些。
- 缓存读取和写入在底层哈希表上执行并附加到内部环形缓冲区。
- 当缓冲区达到阈值时,会将任务提交给
Caffeine.executor
以调用Cache.cleanUp
。 - 当此维护周期运行时(处于锁定状态),
- 缓冲区被排空,事件根据驱逐策略重播(例如 LRU 重新排序)
- 丢弃任何可驱逐的条目,并将任务提交给
Caffeine.executor
以调用RemovalListener.onRemoval
。 - 下一个条目到期之前的持续时间是 calculated 并提交给调度程序。这由 pacer 保护,因此通过确保在计划任务之间发生 ~1s 来避免过度计划。
- 当调度程序运行时,一个任务被提交到
Caffeine.executor
以调用Cache.cleanUp
(参见 #3)。
调度程序执行最少的工作,任何处理都推迟到执行程序。由于使用 O(1) 算法,维护工作很便宜,因此它可能经常根据使用活动发生。它针对小批量工作进行了优化,因此在计划调用之间强制执行约 1 秒的延迟有助于每次调用捕获更多工作。如果下一个过期事件发生在遥远的未来,那么调度程序将在此之前不会运行,尽管调用线程可能会由于它们在缓存上的活动而触发维护周期(参见 #1,2)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。