简介
如题,ThreadPoolExecutor 会拒绝提交上来的 Task ?这个问题其实在上文已经有提到,文档上的第三项描述就提到了
3、If a request cannot be queued, a new thread is created unless this would exceed maximumPoolSize, in which case, the task will be rejected.
解读 Task 被 Rejected 的前提就是:1、不能进入队列,队列元素到达上限; 2、线程数已经到达设置的最大值。此时,Task 将会被拒绝。其实还有一个情况,那就是 ThreadPoolExecutor 被 shutdown 了。
针对 ThreadPoolExecutor 的拒绝处理,JDK 提供了 RejectedExecutionHandler 接口的,接口描述:A handler for tasks that cannot be executed by a ThreadPoolExecutor. 所以咱们是可以自定义拒绝处理器的,那么 JDK 又给了什么默认的拒绝处理方案呢?
目前 JDK 提供了4种实现,全部都是 ThreadPoolExecutor 的内部类:
1、ThreadPoolExecutor.AbortPolicy:直接抛出 RejectedExecutionException 异常,默认的拒绝方式。
AbortPolicy 源码截图2、ThreadPoolExecutor.CallerRunsPolicy:在 ThreadPoolExecutor 未 shutdown 的情况下直接调用 Task 的 run 函数,相当于提交 Task 的线程在执行 Task。
CallerRunsPolicy 源码截图3、ThreadPoolExecutor.DiscardPolicy:抛弃,什么都不做
DiscardPolicy 源码截图4、ThreadPoolExecutor.DiscardOldestPolicy:在 ThreadPoolExecutor 未 shutdown 的情况下抛弃目前队列中最早的任务,然后再重复执行一次execute 操作,可能会出现递归抛弃的情况
DiscardOldestPolicy 源码截图那么 RejectedExecutionHandler 的设计在实际生产环境中有什么作用?如果比较核心的任务被拒绝处理了,可以发起报警提示,或者进行动态扩容等。
ThreadPoolExecutor 的 Hook 函数
void beforeExecute(Thread t, Runnable task):参数 t 为线程池里的线程对象, task 为提交的任务。该函数会在 task.run() 之前被调用,如果 beforeExecute 抛出异常,task 将不会被执行。
afterExecute(Runnable task, Throwable t):参数 task 为提交的任务,t 为 task.run() 过程中抛出的 Exception 或 Error,注意,这里的参数 t 的类型是 Throwable 。
那这里的预留接口的设计有什么作用呢?简单的一个设想,我需要知道核心业务 Task 的异常执行数,甚至执行时间,TPS…… 这些业务需求还是很有价值的。
到这里,ThreadPoolExecutor 的大概其实已经讲解的差不多,这些个人认为只要孜孜不倦的阅读 API 文档都能掌握,这里强调的是 官方的 API 文档,而不是一堆百度结果的集合,技术解读方面,百度的结果在我看来可以用 谣言 来代替来。感谢大家的阅读,如果有任何疑问,请给我留言,我期待和你讨论、分享!
网友评论