当 Executor 已经关闭,并且 Executor 将有限边界用于最大线程和工作队列容量,且已经饱和时,在方法 execute(java.lang.Runnable) 中提交的新任务将被拒绝。在以上两种情况下,execute 方法都将调用其 RejectedExecutionHandler 的 RejectedExecutionHandler.rejectedExecution(java.lang.Runnable, java.util.concurrent.ThreadPoolExecutor) 方法。下面提供了四种预定义的处理程序策略:
A. 在默认的 ThreadPoolExecutor.AbortPolicy 中,处理程序遭到拒绝将抛出运行时 RejectedExecutionException。
B. 在 ThreadPoolExecutor.CallerRunsPolicy 中,线程调用运行该任务的 execute 本身。此策略提供简单的反馈控制机制,能够减缓新任务的提交速度。
C. 在 ThreadPoolExecutor.DiscardPolicy 中,不能执行的任务将被删除。
D. 在 ThreadPoolExecutor.DiscardOldestPolicy 中,如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行程序(如果再次失败,则重复此过程)。
定义和使用其他种类的 RejectedExecutionHandler 类也是可能的,但这样做需要非常小心,尤其是当策略仅用于特定容量或排队策略时。
挂钩方法
此类提供 protected 可重写的 beforeExecute(java.lang.Thread, java.lang.Runnable) 和 afterExecute(java.lang.Runnable, java.lang.Throwable) 方法,这两种方法分别在执行每个任务之前和之后调用。它们可用于操纵执行环境;例如,重新初始化 ThreadLocal、搜集统计信息或添加日志条目。此外,还可以重写方法 terminated() 来执行 Executor 完全终止后需要完成的所有特殊处理。
如果挂钩或回调方法抛出异常,则内部辅助线程将依次失败并突然终止。
队列维护
方法 getQueue() 允许出于监控和调试目的而访问工作队列。强烈反对出于其他任何目的而使用此方法。remove(java.lang.Runnable) 和 purge() 这两种方法可用于在取消大量已排队任务时帮助进行存储回收。
一、例子
创建 TestThreadPool 类:
创建 ThreadPoolTask类:
执行结果:
创建任务并提交到线程池中:task@ 1
开始执行任务:task@ 1
创建任务并提交到线程池中:task@ 2
开始执行任务:task@ 2
创建任务并提交到线程池中:task@ 3
创建任务并提交到线程池中:task@ 4
开始执行任务:task@ 3
创建任务并提交到线程池中:task@ 5
开始执行任务:task@ 4
创建任务并提交到线程池中:task@ 6
创建任务并提交到线程池中:task@ 7
创建任务并提交到线程池中:task@ 8
开始执行任务:task@ 5
开始执行任务:task@ 6
创建任务并提交到线程池中:task@ 9
开始执行任务:task@ 7
创建任务并提交到线程池中:task@ 10
开始执行任务:task@ 8
开始执行任务:task@ 9
开始执行任务:task@ 10