网站首页 > java教程 正文
在日常开发过程中总是以单线程的思维去编码,没有考虑到在多线程状态下的运行状况。由此引发的结果就是请求过多,应用无法响应。为了解决请求过多的问题,又衍生出了线程池的概念。通过“池”的思想,从而合理的处理请求。本文记录了Java中线程池的使用及工作原理,如有错误,欢迎指正。总结了一张Java多线程图谱分享给大家:
什么是线程池?
线程池是一种用于实现计算机程序并发执行的软件设计模式。线程池维护多个线程,等待由调度程序分配任务以并发执行,该模型提高了性能,并避免了由于为短期任务频繁创建和销毁线程而导致的执行延迟。
线程池要解决什么问题?
说到线程池就一定要从线程的生命周期讲起。
从图中可以了解无论任务执行多久,每个线程都要经历从生到死的状态。而使用线程池就是为了避免线程的重复创建,从而节省了线程的New至Runnable, Running至Terminated的时间;同时也会复用线程,最小化的节省系统资源,于此同时提高了响应速度。
线程池的使用
线程池的创建
使用ThreadPoolExecutor并配置7个参数完成线程池的创建
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
corePoolSize
线程池中核心线程的最大值
maximumPoolSize
线程池中最大线程数
keepAliveTime
非核心线程空闲的存活时间大小
unit
keepAliveTime的单位,常用的有秒、分钟、小时等
workQueue
阻塞队列类型
threadFactory
线程工厂,用于配置线程的名称,是否为守护线程等
handler
线程池的拒绝策略
常用阻塞队列
ArrayBlockingQueue
底层基于数组的实现的有界阻塞队列
LinkedBlockingQueue 底层基于单链表的阻塞队列,可配置容量,不配置容量默认为Integer.MAX_VALUE
线程工厂
在《阿里巴巴Java开发手册》中强制要求指定线程的名称
由于工作是使用hutool比较多,里面也包含对ThreadFactory的封装,可以很方便的指定名称
ThreadFactory threadFactory = ThreadFactoryBuilder.create().setNamePrefix("myThread-").build();
拒绝策略
当线程池内工作线程数大于maximumPoolSize时,线程就不再接受任务,执行对应的拒绝策略;目前支持的拒绝策略有四种:
1.AbortPolicy(默认):丢弃任务并抛出RejectedExecutionException异常
2.CallerRunsPolicy:由调用者处理
3.DiscardOldestPolicy:丢弃队列中最前面的任务,并重新入队列
4.DiscardPolicy:丢弃任务但不抛出异常
线程池的执行逻辑
// 创建线程工厂
ThreadFactory threadFactory = ThreadFactoryBuilder.create().setNamePrefix("myThread-").build();
// 创建线程池
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100), threadFactory, new ThreadPoolExecutor.AbortPolicy());
execute()方法
// 组合值;保存了线程池的工作状态和工作线程数
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
public void execute(Runnable command) {
// 任务为空 抛出NPE
if (command == null)
throw new NullPointerException();
// 获取线程池状态
int c = ctl.get();
// 如果工作线程数小于核心线程数就创建新线程
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
// 如果线程池处于Running状态,就把任务放在队列尾部
if (isRunning(c) && workQueue.offer(command)) {
// 重新检查线程池状态
int recheck = ctl.get();
// 如果线程池不是Running状态,就移除刚才添加的任务,并执行拒绝策略
if (! isRunning(recheck) && remove(command))
reject(command);
// 是Running状态,就添加线程
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
// 添加任务失败,执行拒绝策略
else if (!addWorker(command, false))
reject(command);
}
// addWorker()完成线程的创建
执行流程
watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=
最后
另外还整理成了40多套PDF文档:全套的Java面试宝典手册,“性能调优+微服务架构+并发编程+开源框架+分布式”等七大面试专栏,包含Tomcat、JVM、MySQL、SpringCloud、SpringBoot、Dubbo、并发、Spring、SpringMVC、MyBatis、Zookeeper、Ngnix、Kafka、MQ、Redis、MongoDB、memcached等等。如果你对这个感兴趣,小编可以免费分享。
资料获取方式:关注小编+转发文章+私信【面试题】获取上述资料~
重要的事情说三遍,转发+转发+转发,一定要记得转发哦!!
猜你喜欢
- 2024-09-19 Java线程池的四种用法与使用场景(java线程池的原理和实现)
- 2024-09-19 尚学堂百战程序员:Java中的线程池
- 2024-09-19 Java线程池深度揭秘(java线程池入门)
- 2024-09-19 Java线程池(java线程池参数详解)
- 2024-09-19 如何更好的使用JAVA线程池(java中线程池的使用)
- 2024-09-19 史上最详细、最系统、最全面Java线程池解析
- 2024-09-19 好文推荐:深入分析Java线程池的实现原理
- 2024-09-19 Java的线程池是怎么回事?来看看这篇文章吧
- 2024-09-19 Java之线程池(java线程池实战)
- 2024-09-19 Java Web应用调优线程池:没你想的那么复杂
你 发表评论:
欢迎- 最近发表
-
- class版本不兼容错误原因分析(class更新)
- 甲骨文Oracle公司为Java的最新LTS版本做出改进
- 「版本发布」Minecraft Java开发版 1.19.4-pre1 发布
- java svn版本管理工具(svn软件版本管理)
- 我的世界1.8.10钻石在第几层(我的世界1.7.2钻石在哪层)
- Java开发高手必备:在电脑上轻松切换多个JDK版本
- 2022 年 Java 开发报告:Java 8 八年不到,开发者都在用什么?
- 开发java项目,选择哪个版本的JDK比较合适?
- Java版本选型终极指南:8 vs 17 vs 21特性对决!大龄程序员踩坑总结
- POI Excel导入(poi excel导入附件)
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)