浅谈Java线程池中的ThreadPoolExecutor工具类

news2025/2/26 15:09:31

 

目录

ThreadPoolExecutor的构造函数

 关于线程池的一些补充

线程池运行原理分析

概念原理解释

整个流程图如下:

一点补充


创建线程池主要有两种方式:

  • 通过Executor工厂类创建,创建方式比较简单,但是定制能力有限
  • 通过ThreadPoolExecutor创建,创建方式比较复杂,但是定制能力强

但我们一般不建议使用Executor工厂类来进行线程的创建。

原因如下:

Executor提供的很多方法默认使用的都是无界的LinkedBlockingQueue,在高负载情况下,无界队列很容易导致OOM——OOM 全称 “Out Of Memory”,表示内存耗尽。当 JVM 因为没有足够的内存来为对象分配空间,并且垃圾回收器也已经没有空间可回收时,就会抛出这个错误。

那么一旦出现了OOM,就会导致所有的请求都无法处理,这个是致命问题。所有要尽量避免使用无界队列——》即慎用Executor来创建线程

 

那么下面让我们详细了解推荐使用的ThreadPoolExecutor这个核心工具类。

ThreadPoolExecutor的构造函数


ThreadPoolExecutor 的构造函数非常复杂,如下面代码所示,这个最完备的构造函数有 7 个参数。
 

ThreadPoolExecutor (
            int corePoolSize,
            int maximumPoolSize,
            long keepAliveTime,
            TimeUnit unit,
            BlockingQueue<Runnable> workQueue,
            ThreadFactory threadFactory,
            RejectedExecutionHandler handler
    )

一起来看看这7个参数的含义分别是什么吧!

corePoolSize

核心线程数,就是该线程池保有的最下线程数

maximumPoolSize

最大线程数

keepAliveTime 和unit 

我们首先要知道线程分为空闲(阻塞等待中)和忙碌(执行任务)两种状态,当一个线程空闲了较长时间,同时此时线程池子中的线程数目大于核心线程数目corePoolSize,该线程就会被销毁回收

keepAlive和unit就是用来衡量空闲时间的,当空闲时间大于keepAliveTime时候(unit是keepAliveTime是时间单位),同时线程数目大于corePoolSize时,该线程就会被注销

workQueue

工作队列(一个阻塞队列,用来存放可执行任务Runnable Task)

threadFactory

通过这个参数你可以自己定义如何创建线程,比如你可以给线程指定一个有意义名称

handler

通过这个参数,你可以自定义任务的拒绝策略,如果线程池中的线程都在忙碌,并且工作队列也满了(前提工作队列是有界队列),此时当有一个新的任务添加进来,提交任务,线程池会拒绝接收。

至于拒绝的策略,你可以通过handler这个参数来指定,ThreadPoolExecutor以及提供了以下四种策略。

  • CallerRunsPolicy:提交任务的线程自己去执行该任务
  • AbortPolicy:默认的拒绝策略,会throw RejectedExecutorException—》这是个运行时异常,编辑器不强制catch、容易忽略,开发人员要谨慎使用(可以自己定义自己的拒绝策略)
  • DiscardPolicy:直接丢弃任务,没人任何异常输出
  • DiscardOldestPolicy:丢弃最古老的任务,,其实就是把最早进入任务队列workQueue的任务给丢弃掉,然后把新任务添加到任务队列中。

 关于线程池的一些补充

线程是一个重量级的对象,应该避免频繁创建和销毁

目前业界线程池的设计,普遍采用的都是生产者 - 消费者模式。


线程池的使用方是生产者,线程池本身是消费者

比如上面我们的任务队列workQueue(生产的Runnable任务就放到了该队列中),这些任务供线程池中的线程执行(消费)

线程池运行原理分析

概念原理解释

1、创建一个线程池,当此时还没有任务提交的时候(阻塞队列workQueue为空的时候,此时默认线程池中是没有线程的,当然了,此时也可以调用prestartThread方法,来预先创建一个核心线程

 

2、当线程池里面还没有线程或者是线程池中存活的线程小于核心线程数corePoolSize的时候,每新提交一个任务,线程池就会专门创建一个新的线程来处理刚刚提交的任务(阻塞队列workQueue中的Runnable任务)。

此时线程池中的线程会一直存活着,即使线程是空闲的,甚至空闲时间超过了keepAliveTime ,线程也不会销毁(此时线程池中的线程小于核心线程数corePoolSize)    

那么这个时候线程就只能等任务队列中什么时候有可执行的任务了(Runnable task) ,才会重写开始执行(变得忙碌起来,在此之前,线程一直是阻塞在那里的——》这也是为什么线程池队列用的是阻塞队列)

3、当线程池中的线程数等于线程核心数corePoolSize,同时任务队列有空间,此时当再有新的任务提交的时候,该任务会被放到任务队列中(workQueue)排队等待执行。而不会在新创建一个线程来执行刚刚提交的任务。

此时之前创建的线程并不会被注销,而是会不断的去拿阻塞队列中的任务,当任务队列中的任务为空的时候,线程会阻塞,直到有任务(Runnable Task)被放进任务队列中。

这也是为什么线程池的任务队列需要是阻塞队列。

我们之前说过Java中的线程池是生产者消费者模型,线程的使用方——》生产可运行的任务Runnable task,并且放到任务队列中)供线程池中的线程进行消费(任务的执行)

4、当线程池的线程数等于线程核心数corePoolsize,并且此时任务队列workQueue是满的状态。

这时如果来了新的Runnable Task,线程池子就会创建新的线程来处理该任务。

直到线程数达到了maximumPoolSize——》就不会再继续创建新的线程来处理任务了。

这些新的线程在执行完了当前的任务后,也不会被销毁。而是执行任务队列中的RunnableTask,(此时线程是忙碌状态,非空闲)当把任务队列中的任务执行完了后(此时线程池中线程数应该是大于corePoolSize的,那么接下来就会有一个判断逻辑——》判断线程是否需要被销毁,当线程因为任务队列为空,陷入阻塞(进入空闲状态)的时间大于keepAliveTime的时候,该线程就会被销毁——》直到线程数等于corePoolSize

5、如果线程池中的线程数目达到了maximumSize,并且此时任务队列也满了。

这种情况下还有新的任务过来,那就直接采用拒绝的处理器进行处理。默认的处理器逻辑是抛出一个RejectedExecutionException异常

整个流程图如下:

 

一点补充

使用线程池,还要注意异常处理的问题,例如通过 ThreadPoolExecutor 对象的 execute() 方法提交任务时,如果任务在执行的过程中出现运行时异常,会导致执行任务的线程终止;不过,最致命的是任务虽然异常了,但是你却获取不到任何通知,这会让你误以为任务都执行得很正常。虽然线程池提供了很多用于异常处理的方法,但是最稳妥和简单的方案还是捕获所有异常并按需处理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/361576.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Git ---- 概述

Git ---- 概述1. 何为版本控制2. 为什么需要版本控制3. 版本控制的工具集中式版本控制工具分布式版本控制工具4. Git 简史5. Git 工作机制6. Git 和代码托管中心Git 是一个免费的、开源的分布式版本控制系统&#xff0c;可以快速高效地处理从小型到大型的各种项目。 Git 易于学…

深入浅出C++ ——继承

文章目录一、继承的相关概念1. 继承的概念2. 继承格式3. 继承方式4. 访问限定符5. 继承基类成员访问方式的变化二、基类和派生类对象赋值转换三、继承中的作用域四、派生类的默认成员函数五、继承与友元六、继承与静态成员七、菱形继承及菱形虚拟继承1. 单继承2. 多继承3. 菱形…

【比赛合集】9场可报名的「创新应用」、「程序设计」大奖赛,任君挑选!

CompHub 实时聚合多平台的数据类(Kaggle、天池…)和OJ类(Leetcode、牛客…&#xff09;比赛。本账号同时会推送最新的比赛消息&#xff0c;欢迎关注&#xff01;更多比赛信息见 CompHub主页 或 点击文末阅读原文以下信息仅供参考&#xff0c;以比赛官网为准目录创新应用赛&…

基于Java+SpringBoot+Vue+Uniapp前后端分离健身预约系统设计与实现

博主介绍&#xff1a;✌全网粉丝3W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战✌ 博主作品&#xff1a;《微服务实战》专栏是本人的实战经验总结&#xff0c;《Spring家族及…

linux集群技术(二)--keepalived(高可用集群)(一)

高可用集群简介keepalived简介 1.高可用集群简介 1.1什么是高可用集群 高可用集群&#xff08;High Availability Cluster&#xff0c;简称HA Cluster&#xff09;&#xff0c;是指以减少服务中断时间为目的的服务器集群技术。它通过保护用户的业务程序对外不间断提供的服务&am…

Vue3后台管理系统(一)基础环境

目录 一、初始化 二、整合Element-Plus 三、路径别名 四、多环境配置 五、反向代理 六、其他依赖 一、初始化 npm init vitelatest vue3-element-admin --template vue-ts 二、整合Element-Plus 1.本地安装Element Plus和图标组件 npm install element-plus npm inst…

code-breaking之javacon

JAVACON 题目 此题 来自P神 的code-breaking中的一道Java题&#xff0c;名为javacon&#xff0c;题目知识点为SpEL注入 题目下载地址&#xff1a;https://www.leavesongs.com/media/attachment/2018/11/23/challenge-0.0.1-SNAPSHOT.jar 运行环境 java -jar challenge-0.…

实用指南:如何在Anolis OS上轻松使用 Kata 安全容器?

文/云原生SIG本篇文章我们将详细介绍怎么轻松在 Anolis OS 上使用 Kata Containers 安全容器&#xff0c;我们将介绍 Kata Container 社区于 2022 年 10 月 10 日最新发行的 Kata3.0.0 的安装部署方式&#xff0c;3.0.0 版本包含了基于袋鼠 RunD 开源的最新 Rust Kata runtime …

AAAI 2023 | 小鹏汽车纽约石溪:在末层激活上作对抗训练的域自适应

原文链接&#xff1a;https://www.techbeat.net/article-info?id4602 作者&#xff1a;吕骋 增强未标记目标域数据的模型预测置信度是无监督域自适应&#xff08;UDA&#xff09; 的一个重要目标。在本文中&#xff0c;作者探讨了末层激活&#xff08;即最后一层线性分类层输入…

以假乱真的手写模拟器?

前些时候给大家推荐了一款word插件叫做“不坑盒子”&#xff0c;这款盒子不仅方便了word的操作&#xff0c;还附带了手写模拟器这样的效果只是在使用的时候不仅需要手动下载字体&#xff0c;而且效果也并不是太理想。 今天小编找到了一款软件--手写模拟器&#xff0c;不仅一键生…

木鱼cms系统审计小结

MuYuCMS基于Thinkphp开发的一套轻量级开源内容管理系统,专注为公司企业、个人站长提供快速建站提供解决方案。 ​​ ‍ 环境搭建 我们利用 phpstudy 来搭建环境&#xff0c;选择 Apache2.4.39 MySQL5.7.26 php5.6.9 &#xff0c;同时利用 PhpStorm 来实现对项目的调试 ​…

求数组中的第k小元素

文章目录第k小的元素&#x1f512;题目&#x1f4a1;分析&#x1f511;题解&#x1f343;不去重版&#x1f343;去重版第k小的元素 &#x1f512;题目 题目来源&#xff1a;3533. 查找第K小数 - AcWing题库 &#x1f4a1;分析 不去重版思路&#xff1a;去重版思路&#xff1a…

华为OD机试 - 斗地主(C++) | 附带编码思路 【2023】

刷算法题之前必看 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD 清单查看地址:https://blog.csdn.net/hihell/category_12199283.html 华为OD详细说明:https://dream.blog.csdn.net/article/details/128980730 华为OD机试题…

一、【cas搭建单点登录】使用cas搭建单点登录服务器

使用cas搭建单点登录服务器 环境要求 JDK 8CAS 5.2tomcat 8 选用5.x的cas版本是应为要是jdk1.8的版本。 cas版本jdk版本5.x86.x117.x17 模板下载 目前cas的官方文档中&#xff0c;cas官方模板分成了5个大类。cas-sso-server 模板下载地址。 在cas的官方模板库中&#xff…

2023年2月22日PMP®项目管理认证课程正式开课

PMP认证是Project Management Institute在全球范围内推出的针对评价个人项目管理知识能力的资格认证体系。国内众多企业已把PMP认证定为项目经理人必须取得的重要资质。 PMP认证是Project Management Institute在全球范围内推出的针对评价个人项目管理知识能力的资格认证体系。…

微服务之Eureka

&#x1f3e0;个人主页&#xff1a;阿杰的博客 &#x1f4aa;个人简介&#xff1a;大家好&#xff0c;我是阿杰&#xff0c;一个正在努力让自己变得更好的男人&#x1f468; 目前状况&#x1f389;&#xff1a;24届毕业生&#xff0c;奋斗在找实习的路上&#x1f31f; &#x1…

【虚拟机】VirtualBox Host-Only + 主机网络共享配置

文章目录创建Host-Only虚拟机配置主机配置其它工作中经常会使用到虚拟机进行各种技术的试验&#xff0c;之前为了省事常用桥接模式&#xff0c;可是我经常变换办公地点&#xff0c;每个办公地点的局域网网段并不一样&#xff0c;所以我采取了仅主机模式网络共享这种方式&#x…

34-Golang中的结构体!!!

Golang中的结构体结构体和结构体变量(实例)的区别和联系结构体变量(实例)在内存中的布局如何声明结构体字段/属性注意事项和细节说明创建结构体实例的四种方式结构体使用细节结构体和结构体变量(实例)的区别和联系 1.结构体是自定义的数据类型&#xff0c;代表一类事物2.结构体…

C++项目——高并发内存池(3)--central cache整体设计

1.central cache的介绍 1.1框架思想 1.1.1哈希映射 centralcache其实也是哈希桶结构的&#xff0c;并且central cache和thread cacha的哈希映射关系是一致的。目的为了&#xff0c;当thread cache某一个哈希桶下没有内存块时&#xff0c;可以利用之前编写的SizeClass::Index…

论文解读 | [CVPR2019] 基于自适应文本区域表示的任意形状场景文本检测

目录 1 研究背景及意义 2 总体设计 3 方法论 3.1 自适应文本区域表示 3.2 文本建议 3.3 建议改进 4 损失函数 5 实验及结果 1 研究背景及意义 现有的场景文本检测方法使用固定点数的多边形来 表示文本区域。例如&#xff0c;水平文本使用2个点(左上/右下)表示文本区域&…