jdk内置4种线程池拒绝策略

一、拒绝策略接口定义
在分析JDK自带的线程池拒绝策略前,先看下JDK定义的 拒绝策略接口,如下:


image.png

接口定义很明确,当触发拒绝策略时,线程池会调用你设置的具体的策略,将当前提交的任务以及线程池实例本身传递给你处理
具体作何处理,不同场景会有不同的考虑,下面看JDK为我们内置了哪些实现:
1、CallerRunsPolicy(调用者运行策略)


f2d42e8fb0be7ebda5c932a7ccb3ef4.png

功能:当触发拒绝策略时,只要线程池没有关闭,就由提交任务的当前线程处理。
使用场景:一般在不允许失败的、对性能要求不高、并发量较小的场景下使用。
因为线程池一般情况下不会关闭,也就是提交的任务一定会被运行,但是由于是调用者线程自己执行的,当多次提交任务时,就会阻塞后续任务执行,性能和效率自然就慢了。

2、AbortPolicy(中止策略)


d42e0cca60b5056d483cfff1e088f48.png

功能:当触发拒绝策略时,直接抛出拒绝执行的异常,中止策略的意思也就是打断当前执行流程。
使用场景:这个就没有特殊的场景了,但是一点要正确处理抛出的异常。
ThreadPoolExecutor中默认的策略就是AbortPolicy,ExecutorService接口的系列ThreadPoolExecutor因为都没有显示的设置拒绝策略,所以默认的都是这个。
但是请注意,ExecutorService中的线程池实例队列都是无界的,也就是说把内存撑爆了都不会触发拒绝策略。
当自己自定义线程池实例时,使用这个策略一定要处理好触发策略时抛的异常,因为他会打断当前的执行流程。
3、DiscardPolicy(丢弃策略)
44a661fe82be38961499b564a8b6edd.png

功能:直接静悄悄的丢弃这个任务,不触发任何动作。
使用场景:如果你提交的任务无关紧要,你就可以使用它。
因为它就是个空实现,会悄无声息的吞噬你的的任务。所以这个策略基本上不用了。
4、DiscardOldestPolicy(弃老策略)
a5fa30550bec6eb22d60e1d65ede8dc.png

功能:如果线程池未关闭,就弹出队列头部的元素,然后尝试执行。
使用场景:这个策略还是会丢弃任务,丢弃时也是毫无声息,但是特点是丢弃的是老的未执行的任务,而且是待执行优先级较高的任务。
基于这个特性,能想到的场景就是,发布消息,和修改消息,当消息发布出去后,还未执行,此时更新的消息又来了,这个时候未执行的消息的版本比现在提交的消息版本要低就可以被丢弃了。
因为队列中还有可能存在消息版本更低的消息会排队执行,所以在真正处理消息的时候一定要做好消息的版本比较。

你可能感兴趣的:(jdk内置4种线程池拒绝策略)