线程池工作中,当任务量很大,超过系统实际承载能力时,如果不去搭理它,系统很可能崩溃,所以jdk内置提供了四种线程池的拒绝策略,可以合理解决这种问题,当线程池中的线程已用完不能再创建,等待队列也排满,如果此时再有新任务,就会触发执行拒绝策略之一。
1.CallerRunsPolicy(调用者运行策略)
一般在不允许失败的,对性能要求不高,并发量较小的场景下使用,因为线程池一般场景下不会关闭,也就是提交的任务一定会被运行,但是由于是调用者线程自己执行的,当多次提交任务时,就会阻塞后续任务执行,性能和效率自然就慢了。当触发拒绝策略时,只要线程池没有关闭,就由提交任务的当前线程处理。
2.AbortPolicy(中止策略)
当触发拒绝策略时,它就会直接抛出拒绝执行的异常,中止策略就是直接打断当前执行的流程。ThreadPoolExecutor中默认的策略就是AbortPolicy,ExecutorService接口系列的ThreadPoolExecutor因为都没有显示的设置拒绝策略,所以默认都是这个;但ExecutorService中的线程池实例队列都是无界的,也就是说把内存撑爆了都不会触发拒绝策略。当自己定义线程池实例时,使用这个策略一定要定义好触发策略时抛出的异常,因为他会打断当前的执行流程。
3.DiscardPolicy(丢弃策略)
如果你提交的任务无关紧要,就可以使用这个策略,因为它就是个空实现,会悄无声息地吞噬你的任务,不会触发任何动作。
4.DiscardOldestPolicy(弃老政策)
这个策略依然会悄无声息地丢弃任务,不触发任何动作,但丢弃的是老的未执行的任务,而且是待执行优先级较高的任务。是否采用此策略,需根据实际业务是否允许丢弃老任务来衡量。
例题
当请求过多,超出线程池负荷的时候,会触发拒绝策略。下列选项中,对于拒绝策略的描述错误的是(C)
A.CallerPolicy,线程调用运行该任务的execute本身,此策略提供简单的反馈控制机制,能够减缓新任务的提交速度
B.AbortPolicy 处理程序遭到拒绝将直接抛出异常,丢弃任务
C.DiscardPolicy 不能执行的任务将被删除。这种策略丢弃任务同时也会抛出异常
D.DiscardOldestPolicy 如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行任务