java线程池工作队列饱和策略代码示例
线程池(Thread Pool) 是并行执行任务收集的实用工具。随着 CPU 引入适合于应用程序并行化的多核体系结构,线程池的作用正日益显现。通过 ThreadPoolExecutor类及其他辅助类,Java 5 引入了这一框架,作为新的并发支持部分。
ThreadPoolExecutor框架灵活且功能强大,它支持特定于用户的配置并提供了相关的挂钩(hook)和饱和策略来处理满队列
Java线程池会将提交的任务先置于工作队列中,在从工作队列中获取(SynchronousQueue直接由生产者提交给工作线程)。那么工作队列就有两种实现策略:无界队列和有界队列。无界队列不存在饱和的问题,但是其问题是当请求持续高负载的话,任务会无脑的加入工作队列,那么很可能导致内存等资源溢出或者耗尽。而有界队列不会带来高负载导致的内存耗尽的问题,但是有引发工作队列已满情况下,新提交的任务如何管理的难题,这就是线程池工作队列饱和策略要解决的问题。
饱和策略分为:Abort 策略, CallerRuns 策略,Discard策略,DiscardOlds策略。
为了更好的理解,我编写一个小的例子。
package concurrency.pool; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class SaturationPolicy { /** * 线程池工作队列已满时,在不同饱和策略下表现 * @param handler 线程池工作队列饱和策略 */ public static void policy(RejectedExecutionHandler handler){ //基本线程2个,最大线程数为3,工作队列容量为5 ThreadPoolExecutor exec = new ThreadPoolExecutor(2,3,0l, TimeUnit.MILLISECONDS,new LinkedBlockingDeque<>(5)); if (handler != null){ exec.setRejectedExecutionHandler(handler); //设置饱和策略 } for (int i = 0; i < 10; i++) { exec.submit(new Task()); //提交任务 } exec.shutdown(); } public static void main(String[] args) { // policy(new ThreadPoolExecutor.AbortPolicy()); // policy((new ThreadPoolExecutor.CallerRunsPolicy())); // policy(new ThreadPoolExecutor.DiscardPolicy()); // policy(new ThreadPoolExecutor.DiscardOldestPolicy()); } //自定义任务 static class Task implements Runnable { private static int count = 0; private int id = 0; //任务标识 public Task() { id = ++count; } @Override public void run() { try { TimeUnit.SECONDS.sleep(3); //休眠3秒 } catch (InterruptedException e) { System.err.println("线程被中断" + e.getMessage()); } System.out.println(" 任务:" + id + "\t 工作线程: "+ Thread.currentThread().getName() + " 执行完毕"); } } }
当工作队列满了,不同策略的处理方式为:
1.Abort策略:默认策略,新任务提交时直接抛出未检查的异常RejectedExecutionException,该异常可由调用者捕获。
在主函数中添加如下代码:
policy(new ThreadPoolExecutor.AbortPolicy());
运行结果为:
程序抛出了RejectedExecutionException,并且一共运行了8个任务(线程池开始能运行3个任务,工作队列中存储5个队列)。当工作队列满了的时候,直接抛出了异常,而且JVM一直不退出(我现在也不知道什么原因)。我们可以看到执行任务的线程全是线程池中的线程。
2.CallerRuns策略:为调节机制,既不抛弃任务也不抛出异常,而是将某些任务回退到调用者。不会在线程池的线程中执行新的任务,而是在调用exector的线程中运行新的任务。
在主函数运行:
policy((new ThreadPoolExecutor.CallerRunsPolicy()));
运行结果
所有的任务都被运行,且有2(10 - 3 -5)个任务是在main线程中执行成功的,8个任务在线程池中的线程执行的。
3.Discard策略:新提交的任务被抛弃。
在main函数中运行
policy(new ThreadPoolExecutor.DiscardPolicy());
通过上面的结果可以显示:没有异常抛出,后面提交的2个新任务被抛弃,只处理了前8(3+5)个任务,JVM退出。
4.DiscardOldest策略:队列的是“队头”的任务,然后尝试提交新的任务。(不适合工作队列为优先队列场景)
在main函数中运行如下方法
policy(new ThreadPoolExecutor.DiscardOldestPolicy());
运行结果:一共运行8个任务,程序结束,后面添加的任务9,任务10被执行了,而前面的任务3,任务4被丢弃。
总结
以上就是本文关于java线程池工作队列饱和策略代码示例的全部内容,希望对大家有所帮助。如有不足之处,欢迎留言指出。感谢朋友们对本站的支持。
- 极客手工:自制51四驱无线遥控小车
- flash:二次贝塞尔曲线应用-生成飞机路径示意图
- 微信小程序重磅功能上线!一键连Wi-Fi/手机变门禁卡
- MySQL下载安装、基本配置、问题处理
- windows下命令行模式中cd命令无效的原因
- 分布式和集群区别?什么是云计算平台?分布式的应用场景?
- 中国移动也要搞自动驾驶,没了SIM卡怎么耍花样?
- python并发编程之多进程理论部分
- 使用concurrent.futures模块并发,实现进程池、线程池
- 人工智能与医疗
- 每周论文清单:知识图谱,文本匹配,图像翻译,视频对象分割
- 进程池、线程池、回调函数
- java学习:weblogic下JNDI及JDBC连接测试(weblogic环境)
- 简单谈谈python的反射机制
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Hibernate进阶篇(三)——transaction简介
- Elastic search N-gram tokenizer
- java.io.IOException: com.esotericsoftware.kryo.KryoException: Encountered unregistered class ID: 110
- io.protostuff.runtime.RuntimeUnsafeFieldFactory cannot have the same number
- dubbo 调用报Null 空指针 ,可能并不是真正的空指针
- Hibernate单表操作(四)——组件属性
- Dubbo consumer消费端启动报错java.lang.RuntimeException: [source error] not available in a static method: h
- Groovy小记it关键字和IDE报错
- 05 . Jenkins定制主题和设置项目构建信息输出颜色
- 腾讯云物联网平台使用报告
- 01 . PostgreSQL简介部署
- 01 . Git常用命令及方法和分支管理
- 记一次公司mssql server密码频繁被改的事件
- elasticsearch 同义词更新,不同集群返回更新节点个数不一样
- H5应用加固防破解-js虚拟机保护方案浅谈