Java 线程池四种拒绝策略
2022/4/27 9:12:36
本文主要是介绍Java 线程池四种拒绝策略,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
jdk1.5版本新增了
JUC
并发包,其中一个包含线程池。
四种拒绝策略:
拒绝策略类型 | 说明 | |
---|---|---|
1 | ThreadPoolExecutor.AbortPolicy | 默认拒绝策略,拒绝任务并抛出任务 |
2 | ThreadPoolExecutor.CallerRunsPolicy | 使用调用线程直接运行任务 |
3 | ThreadPoolExecutor.DiscardPolicy | 直接拒绝任务,不抛出错误 |
4 | ThreadPoolExecutor.DiscardOldestPolicy | 触发拒绝策略,只要还有任务新增,一直会丢弃阻塞队列的最老的任务,并将新的任务加入 |
预先配置
配置线程池。
- 核心线程和最大线程都尽量设置的小一点,分别设置成 1 和 2
- 阻塞队列设置固定长度的有界队列,长度为 1
- 线程工厂设置默认线程工厂
// 核心线程数 int corePoolSize = 1; // 最大线程数 int maximumPoolSize = 2; // 线程存活时间 long keepAliveTime = 10; // 线程存活时间单位 TimeUnit unit = TimeUnit.SECONDS; // 有界队列 遵循 FIFO 原则 BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(1); // 线程工厂 ThreadFactory threadFactory = Executors.defaultThreadFactory();
创建线程任务
创建线程任务,一个线程任务执行一秒:
class TaskThread implements Runnable{ private int i; public TaskThread(int i) { this.i = i; } @Override public void run() { try { TimeUnit.SECONDS.sleep(2); System.out.println("执行任务:" + i); } catch (InterruptedException e) { e.printStackTrace(); } } }
拒绝策略一:AbortPolicy
默认拒绝策略,拒绝任务并抛出任务
// 拒绝策略 默认拒绝策略,拒绝任务并抛出异常: RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy(); ThreadPoolExecutor threadPool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler); for (int i = 1; i <= 5; i++) { try { threadPool.execute(new TaskThread(i)); } catch (Exception e) { System.out.println("【任务" + i + "】报错:" + e.getMessage()); } }
输出
【任务】4报错:Task com.test.controller.ThreadPoolController$TaskThread@5c0369c4 rejected from java.util.concurrent.ThreadPoolExecutor@50675690[Running, pool size = 2, active threads = 2, queued tasks = 1, completed tasks = 0] 【任务】5报错:Task com.test.controller.ThreadPoolController$TaskThread@31b7dea0 rejected from java.util.concurrent.ThreadPoolExecutor@50675690[Running, pool size = 2, active threads = 2, queued tasks = 1, completed tasks = 0] 执行任务:1 执行任务:3 执行任务:2
最大线程数 + 阻塞队列 = 3,执行到4,5的时候就抛出错误。这里需要用 try catch
捕获异常。任务1、2、3正常执行。
如果提交的任务都要执行,可以将抛出的错误任务存入在redis中,然后定时从
redis
中获取任务,再提交执行。
拒绝策略二:CallerRunsPolicy
调用线程运行多余的任务。
更换拒绝策略,将上面的 AbortPolicy
换成 CallerRunsPolicy
。
RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();
执行任务,输出:
执行任务:1 执行任务:4 执行任务:3 执行任务:2 执行任务:5
最大线程数 + 阻塞队列 = 3,多余的任务还是继续被执行。
拒绝策略三:DiscardPolicy
拒绝任务,不会抛出错误。
更换策略,将CallerRunsPolicy
换成DiscardPolicy
:
RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy();
执行任务,输出:
执行任务:1 执行任务:3 执行任务:2
多余的线程任务提交被拒绝,而只执行最大线程数 + 阻塞队列 数量的任务,并且不会抛出错误。
拒绝策略四:DiscardOldestPolicy
只要还有任务新增,一直会丢弃阻塞队列的最老的任务,并将新的任务加入到阻塞队列中。
更换策略,将DiscardPolicy
换成DiscardOldestPolicy
:
RejectedExecutionHandler handler3 = new ThreadPoolExecutor.DiscardOldestPolicy();
执行任务,输出:
执行任务:3 执行任务:1 执行任务:5
任务的执行顺序是 核心线程数 —> 阻塞队列 —> 最大线程数,其中任务1,任务3提交成功。
- 任务2因为在阻塞队列中,
- 后面的任务4把任务2挤掉,
- 任务5又把任务4挤掉,所以最后执行的是任务5。
总结
本文介绍了线程四种拒绝策略,当工作任务大于最大线程 + 阻塞队列会执行阻塞队列。
- AbortPolicy 默认策略,拒绝任务,并抛出异常
- CallerRunsPolicy 调用线程执行对于的任务
- DiscardPolicy 拒绝任务,不会抛出异常
- DiscardOldestPolicy 有多余的任务,把阻塞队列最老的任务丢弃,放入新的任务,直到没有新的任务。
如果觉得文章对你有帮助的话,请点个推荐吧!
这篇关于Java 线程池四种拒绝策略的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-29设计Element UI表单组件居然如此简单!
- 2024-12-28一步到位:购买适合 SEO 的域名全攻略
- 2024-12-27OpenFeign服务间调用学习入门
- 2024-12-27OpenFeign服务间调用学习入门
- 2024-12-27OpenFeign学习入门:轻松掌握微服务通信
- 2024-12-27OpenFeign学习入门:轻松掌握微服务间的HTTP请求
- 2024-12-27JDK17新特性学习入门:简洁教程带你轻松上手
- 2024-12-27JMeter传递token学习入门教程
- 2024-12-27JMeter压测学习入门指南
- 2024-12-27JWT单点登录学习入门指南