当前位置: 首页 > 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 文件下面对两种模式的…...

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

【网络安全产品大调研系列】2. 体验漏洞扫描

前言 2023 年漏洞扫描服务市场规模预计为 3.06&#xff08;十亿美元&#xff09;。漏洞扫描服务市场行业预计将从 2024 年的 3.48&#xff08;十亿美元&#xff09;增长到 2032 年的 9.54&#xff08;十亿美元&#xff09;。预测期内漏洞扫描服务市场 CAGR&#xff08;增长率&…...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器&#xff0c;其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机&#xff08;Virtual Host&#xff09;。 1. 简介 Nginx 使用 server_name 指令来确定…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

短视频矩阵系统文案创作功能开发实践,定制化开发

在短视频行业迅猛发展的当下&#xff0c;企业和个人创作者为了扩大影响力、提升传播效果&#xff0c;纷纷采用短视频矩阵运营策略&#xff0c;同时管理多个平台、多个账号的内容发布。然而&#xff0c;频繁的文案创作需求让运营者疲于应对&#xff0c;如何高效产出高质量文案成…...

站群服务器的应用场景都有哪些?

站群服务器主要是为了多个网站的托管和管理所设计的&#xff0c;可以通过集中管理和高效资源的分配&#xff0c;来支持多个独立的网站同时运行&#xff0c;让每一个网站都可以分配到独立的IP地址&#xff0c;避免出现IP关联的风险&#xff0c;用户还可以通过控制面板进行管理功…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

libfmt: 现代C++的格式化工具库介绍与酷炫功能

libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库&#xff0c;提供了高效、安全的文本格式化功能&#xff0c;是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全&#xff1a…...

ZYNQ学习记录FPGA(一)ZYNQ简介

一、知识准备 1.一些术语,缩写和概念&#xff1a; 1&#xff09;ZYNQ全称&#xff1a;ZYNQ7000 All Pgrammable SoC 2&#xff09;SoC:system on chips(片上系统)&#xff0c;对比集成电路的SoB&#xff08;system on board&#xff09; 3&#xff09;ARM&#xff1a;处理器…...