当前位置: 首页 > news >正文

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

 

目录

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

相关文章:

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

目录 ThreadPoolExecutor的构造函数 关于线程池的一些补充 线程池运行原理分析 概念原理解释 整个流程图如下&#xff1a; 一点补充 创建线程池主要有两种方式&#xff1a; 通过Executor工厂类创建&#xff0c;创建方式比较简单&#xff0c;但是定制能力有限通过ThreadPoo…...

分析过程:服务器被黑安装Linux RootKit木马

前言 疫情还没有结束&#xff0c;放假只能猫家里继续分析和研究最新的攻击技术和样本了&#xff0c;正好前段时间群里有人说服务器被黑&#xff0c;然后扔了个样本在群里&#xff0c;今天咱就拿这个样本开刀&#xff0c; 给大家研究一下这个样本究竟是个啥&#xff0c;顺便也给…...

运动型蓝牙耳机推荐哪款、最新运动蓝牙耳机推荐

提起运动耳机&#xff0c;如今很多运动爱好者和职业教练员们&#xff0c;都会向萌新推荐骨传导运动耳机。骨传导耳机解决了入耳式蓝牙耳机掉落的问题&#xff0c;佩戴相当舒服。骨传导耳机在佩戴过程中解放了双耳&#xff0c;不会因为耳机堵住耳朵&#xff0c;听不到环境音&…...

Python爬虫(9)selenium爬虫后数据,存入mongodb实现增删改查

之前的文章有关于更多操作方式详细解答&#xff0c;本篇基于前面的知识点进行操作&#xff0c;如果不了解可以先看之前的文章 Python爬虫&#xff08;1&#xff09;一次性搞定Selenium(新版)8种find_element元素定位方式 Python爬虫&#xff08;2&#xff09;-Selenium控制浏览…...

gulimall技术栈笔记

文章目录1.项目背景1.1电商模式1.2谷粒商城2.项目架构图3.项目技术&特色4.项目前置要求5.分布式基础概念5.1微服务5.2集群&分布式&节点5.3远程调用5.4负载均衡5.5服务注册/发现&注册中心5.6配置中心5.7服务熔断&服务降级5.7.1服务熔断5.7.2服务降级5.8API网…...

vue3生命周期钩子以及使用方式

按照生命周期的顺序来排列&#xff1a; onBeforeMount() DOM挂载前调用 注册一个钩子&#xff0c;在组件被挂载之前被调用。 当这个钩子被调用时&#xff0c;组件已经完成了其响应式状态的设置&#xff0c;但还没有创建 DOM 节点。它即将首次执行 DOM 渲染过程。 onMount(…...

以假乱真的手写模拟器?

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

每日一题——L1-069 胎压监测(15)

L1-069 胎压监测 分数 15 小轿车中有一个系统随时监测四个车轮的胎压&#xff0c;如果四轮胎压不是很平衡&#xff0c;则可能对行车造成严重的影响。 让我们把四个车轮 —— 左前轮、右前轮、右后轮、左后轮 —— 顺次编号为 1、2、3、4。本题就请你编写一个监测程序&#…...

17_FreeRTOS事件标志组

目录 事件标志组 事件标志组与队列、信号量的区别 事件标志组相关API函数介绍 实验源码 事件标志组 事件标志位:用一个位,来表示事件是否发生 事件标志组是一组事件标志位的集合,可以简单的理解事件标志组,就是一个整数。 事件标志组的特点: 它的每一个位表示一个事件(…...

美团前端常考手写面试题总结

实现观察者模式 观察者模式&#xff08;基于发布订阅模式&#xff09; 有观察者&#xff0c;也有被观察者 观察者需要放到被观察者中&#xff0c;被观察者的状态变化需要通知观察者 我变化了 内部也是基于发布订阅模式&#xff0c;收集观察者&#xff0c;状态变化后要主动通知观…...

MyBatis基于XML的详细使用——动态sql

目录 动态sql if where trim foreach choose、when、otherwise set bind sql MyBatis常用OGNL表达式 动态sql 动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架&#xff0c;你应该能理解根据不同条件拼接 SQL 语句有多痛苦&#xff0c;例如…...

CMake编译opencv4.6

openCV系列文章目录 文章目录openCV系列文章目录前言一、准备工作二、使用步骤1.使用CMake编译openCV总结前言 最近在项目中遇到图片处理&#xff0c;一拍脑袋就想到大名鼎鼎的opencv 一、准备工作 1.openCV官网下载 2.CMake官方下载 3.vs2019官方下载 二、使用步骤 1.使用…...

数据分片(mycat)

1. 数据分片概念&#xff1a; 1.1. 分库分表 什么是分库分表&#xff1a; 将存放在一台数据库服务器中的数据&#xff0c;按照特定方式&#xff08;指的是程序开发的算法&#xff09;进行拆分&#xff0c;分散存放到多台数据库服务器中&#xff0c;以达到分散单台服务器负载的…...

基于STM32设计的倒车雷达系统(超声波模块多方位测距应用)

一、项目背景 汽车高科技产品家族中,专为倒车泊位设置的“倒车雷达”应运而生,倒车雷达的加装可以解决驾驶人员的后顾之忧,大大降低到车事故的发生。汽车倒车雷达全称为“倒车防撞雷达”,也叫“泊车辅助装置”,是汽车泊车安全辅助装置,能以声音或者更为直观的显示来告知…...

Robot Framework + Selenium2Library环境下,结合Selenium Grid实施分布式自动化测试

最近一段时间&#xff0c;公司在推行自动化测试流程&#xff0c;本人有幸参与了自定义通用控件的关键字封装和脚本辅助编写、数据驱动管理、测试用例执行管理等一系列工具软件的研发工作&#xff0c;积累了一些经验&#xff0c;在此与大家做一下分享&#xff0c;也算是做一个总…...

洛谷——前缀和与差分

前缀和与差分 文章目录前缀和与差分应用总结前缀和截断数组思路代码最大加权矩形题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1提示思路代码差分海底高铁题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1提示思路代码改变数组元素思路代码应用总结 前缀和用来…...

离线内网环境部署更新问题记录

文章目录低级错误错误一 配置文件参数错误错误二 文件位置错误新遇到的错误其他遇到的问题经验教训低级错误 错误一 配置文件参数错误 在与现场实施人员沟通时&#xff0c;出现信息错位&#xff0c;实施人员发来的截图里的ip地址不是正在使用的ip地址&#xff08;机器c重装系…...

【Git】Git是什么?简单说说Git的工作机制?Git的常用命令有那些?

目录 一、Git是什么? 二、简单说说Git的工作机制&#xff1f; 三、Git的常用命令有那些&#xff1f; &#x1f49f; 创作不易&#xff0c;不妨点赞&#x1f49a;评论❤️收藏&#x1f499;一下 一、Git是什么? Git 是一个免费的、开源的分布式版本控制系统&#xff0c;可…...

《精通Spring4.x 企业应用开发实战》第1章 Spring概述

目录标题前言一、Spring带给我们什么二、Spring体系结构三、Spring4.0新特性核心容器的增强泛型依赖注入Map依赖注入Lazy延迟依赖注入List注入Conditional 注解CGLIB 代理类增强其他四、Spring 子项目总结前言 汇总&#xff1a;《精通Spring4.x 企业应用开发实战》 一、Spring带…...

【Spring Cloud Alibaba】003-Nacos 概述与单机搭建

【Spring Cloud Alibaba】003-Nacos 概述与单机搭建 文章目录【Spring Cloud Alibaba】003-Nacos 概述与单机搭建一、Nacos 概述0、新技术学习思路推荐1、什么是 Nacos2、架构图架构图架构图信息二、Nacos 单机搭建1、下载与启动下载地址编辑 startup.cmd 文件下面对两种模式的…...

如何使用 API 工具做 Websocket 测试

在 API 测试中&#xff0c;对 Websocket 协议的支持呼声越来越高&#xff0c;今天给大家推荐一款 开源的 API 管理工具——Postcat&#xff0c;以及教教大家&#xff0c;如何利用 API 管理工具做 Websocket 测试。 在线 Demo 链接&#xff1a;Postcat - Open Source API Ecosys…...

90%的人都理解错了HTTP中GET与POST的区别

Get和Post是HTTP请求的两种基本方法&#xff0c;要说它们的区别&#xff0c;接触过WEB开发的人都能说出一二。 最直观的区别就是Get把参数包含在URL中&#xff0c;Post通过request body传递参数。 你可能自己写过无数个Get和Post请求&#xff0c;或者已经看过很多权威网站总结…...

【C++】秋招实习面经汇总篇

C面经汇总 系列综述&#xff1a; 目的&#xff1a;本系列是个人整理为了秋招和实习面试的&#xff0c;整理期间苛求每个知识点&#xff0c;平衡背诵量与深入程度。 来源&#xff1a;材料主要源于阿秀的笔记和《王道考研复习指导》进行的&#xff0c;每个知识点的修正和深入主要…...

干货分享:2023欧美市场分析与机会

1、2023年欧美市场分析美国是⼀个消费大国&#xff0c;正常情况下做外贸不可忽略的市场。如何找客户&#xff1a;专注产业链 。产业链对接&#xff0c;其上游是什么&#xff0c;那么他就是我的客户 ( 原材料-⼯⼚)南美洲是北美的经济殖民地(矿产资源农产品)&#xff0c;非洲仍然…...

介绍Kadence Elements元素模板:按您的方式设计网站

随着 Kadence Pro 1.0.4 和 Kadence Blocks Pro 1.5.8 的发布&#xff0c;Kadence 团队很高兴地宣布推出最强大的新方法&#xff0c;帮助网站所有者使用 Kadence Elements Templates 创建动态和高度定制的 WordPress 网站。如果您曾经创建过 WordPress 网站&#xff0c;并且发现…...

物联网发展的重要通信技术Wi-Fi

Wi-Fi 可以适应各种场景的联网需求 Wi-Fi 在实现物联网创新方面发挥了基础性作用&#xff0c;提供了广泛的连接性&#xff0c;将各种“事物”相互连接、连接到互联网&#xff0c;以及连接到全球使用的 180 亿台 Wi-Fi 设备。物联网的经济潜力是无限的&#xff0c;Wi-Fi 为智能…...

OSS上传(Java和Js)

OSS上传&#xff08;Java和Js&#xff09;准备工作创建RAM用户创建角色创建权限策略给角色授予权限策略获取临时访问凭证Java普通上传OSSJava分片上传OSSJS普通上传OSSJS分片上传OSS使用RAM用户或STS方式访问 由于阿里云账号AccessKey拥有所有API访问权限&#xff0c;建议遵循阿…...

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

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

小公司“混”的3年,我认真做了5件事,真的受益终生

小公司“混”的3年&#xff0c;我认真做了5件事&#xff0c;真的受益终生 目录&#xff1a;导读 功能测试很重要但不值钱 自动化测试在小公司没市场&#xff0c;但是你得会 给自己的一些忠告 第一件事&#xff1a;分清阶段&#xff0c;制定计划 第二件事&#xff1a;梳理…...

Linux Crontab命令定时任务基本语法与操作教程

Linux Crontab命令定时任务基本语法与操作教程 一、Crontab查看编辑重启 1、查看crontab定时执行任务列表 crontab -l 2、编辑crontab定时执行任务 crontab -e 3、删除crontab定时任务 crontab -r 4、相关命令&#xff1a; sudo service crond start #启动服务 sudo …...