线程池拒绝策略概览
- AbortPolicy:抛出
RejectedExecutionException
拒绝新任务。 - CallerRunsPolicy:调用线程执行被拒绝的任务,不丢弃任务。
- DiscardPolicy:直接丢弃新任务。
- DiscardOldestPolicy:丢弃最早的未处理任务。
CallerRunsPolicy 策略详解
- 适用场景:当任务不能被丢弃,且应用程序可以容忍处理延迟时。
- 工作机制:如果线程池未关闭,执行
execute
方法的线程将直接运行被拒绝的任务。
CallerRunsPolicy 策略的风险
- 主线程阻塞:如果被拒绝的任务非常耗时,并且是主线程提交的,可能会导致主线程阻塞。
- 性能影响:可能导致程序整体性能下降,因为新任务的提交速度会降低。
CallerRunsPolicy 策略的解决方案
- 增加队列容量:在内存允许的情况下,增加阻塞队列的大小,以容纳更多任务。
- 调整线程池参数:调整
maximumPoolSize
以提高任务处理速度,减少内存溢出的风险。
任务持久化方案
- 自定义拒绝策略:实现
RejectedExecutionHandler
接口,将无法立即处理的任务存储到持久化存储中,如 MySQL 数据库。 - 混合式阻塞队列:继承
BlockingQueue
接口,实现一个结合了数据库和ArrayBlockingQueue
的队列,优先从数据库中获取任务。
其他框架的拒绝策略示例
- Netty:创建一个线程池外的线程来处理任务,可能需要良好的硬件支持。
- ActiveMQ:尝试在指定时效内将任务入队,以保证最大交付。
实现逻辑
- 自定义拒绝策略负责将暂时无法处理的任务持久化存储。
- 混合式阻塞队列在取任务时优先从数据库中读取,再从
ArrayBlockingQueue
中获取。
总结
选择 CallerRunsPolicy
拒绝策略可以在不允许丢弃任务的情况下确保任务被执行。然而,需要考虑其潜在风险,并可能需要结合任务持久化和其他策略来优化性能和资源利用。