我们之前讲过的任务拒绝模块是线程池的保护部分,线程池有一个最大的容量,当线程池的任务缓存队列已满,并且线程池中的线程数目达到maximumPoolSize时,就需要拒绝掉该任务,采取任务拒绝策略,保护线程池。拒绝策略其实是一个接口,用户可以通过实现这个接口去定制拒绝策略,也可以选择JDK提供的四种已有拒绝策略。下面我们就来讲一讲JDK内置的4种拒绝策略。
一般在不允许失败的、对性能要求不高、并发量较小的场景下使用,因为线程池一般情况下不会关闭,也就是提交的任务一定会被运行,但是由于是调用者线程自己执行的,当多次提交任务时,就会阻塞后续任务执行,性能和效率自然就慢了。当触发拒绝策略时,只要线程池没有关闭,就由提交任务的当前线程处理。
当触发拒绝策略时,它就会直接抛出拒绝执行的异常,中止策略就是直接打断当前执行的流程。它没有特殊的使用场景,但是一点要正确处理抛出的异常。ThreadPoolExecutor中默认的策略就是AbortPolicy,ExecutorService接口的系列ThreadPoolExecutor因为都没有显示的设置拒绝策略,所以默认的都是这个。但是请注意,ExecutorService中的线程池实例队列都是无界的,也就是说把内存撑爆了都不会触发拒绝策略。当自己自定义线程池实例时,使用这个策略一定要处理好触发策略时抛的异常,因为他会打断当前的执行流程。
如果你提交的任务无关紧要,你就可以使用它 。因为它就是个空实现,会悄无声息的吞噬你的的任务。它就是直接静悄悄的丢弃这个任务,不触发任何动作。所以这个策略基本上不用了。
这个策略依然会丢弃任务,丢弃时也是无声无息,但丢弃的是老的未执行的任务,而且是待执行优先级较高的任务。基于这个特性,我能想到的场景就是,发布消息,和修改消息,当消息发布出去后,还未执行,此时更新的消息又来了,这时未执行的消息的版本比现在低就可以被丢弃了。因为队列中还可能存在消息版本更低的消息会排队执行,所以在真正处理消息的时候一定要做好消息的版本比较。此拒绝策略,是一种喜新厌旧的拒绝策略。是否要采用此种拒绝策略,还得根据实际业务是否允许丢弃老任务来认真衡量。
正如我们开头所说的那样,拒绝策略其实是一个接口,那么如何实现这个接口来实现拒绝策略呢?我们可以到动力节点在线的免费视频课程中寻找你需要的答案。
提枪策马乘胜追击04-21 20:01
代码小兵92504-17 16:07
代码小兵98804-25 13:57
杨晶珍05-11 14:54