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

Java线程池知识点梳理

Java线程池知识点梳理

什么是线程池?

线程在系统中创建的成本是相对比较高的,所以使用”池化“的思想,设计线程池,有大量任务需要执行时,可以直接从线程池中使用已经创建好的线程直接去执行。减少线程的创建和销毁带来的开销,线程池通过工作队列和线程管理来实现高效的任务执行。使用少量的线程数满足最大的吞吐量。

线程池的主要组成部分包括工作线程、任务队列、线程管理器等。线程池的设计有助于优化多线程程序的性能和资源利用,同时简化了线程的管理和复用的复杂性。

线程池的实现

Java线程池的核心实现类是ThreadPoolExecutor,主要类图如下:

Executor
execute(Runnable command)
ExecutorService
shutdown()
isShutdown() : boolean
isTerminated() : boolean
submit(Callable<T> task) : Future<T>
ThreadPoolExecutor
execute(Runnable command)
AbstractExecutorService

线程池的状态

  1. RUNNING: 线程池一旦被创建,就处于RUNNING状态,任务数为0,能够接收新任务,对已排队的任务进行处理。
  2. SHUTDOWN:不接收新任务,但能处理已排队的任务。当调用线程池的shutdown()方法时,线程池会由RUNNING转变为SHUTDOWN状态。
  3. STOP:不接收新任务,不处理已排队的任务,并且会中断正在处理的任务。当调用线程池的shutdownNow()方法时,线程池会由RUNNING或SHUTDOWN转变为STOP状态。
  4. TIDYING:当线程池在SHUTDOWN状态下,任务队列为空且执行中任务为空,或者线程池在STOP状态下,线程池中执行中任务为空时,线程池会变为TIDYING状态,会执行terminated()方法。这个方法在线程池中是空实现,可以重写该方法进行相应的处理。
  5. TERMINATED:线程池彻底终止。线程池在TIDYING状态执行完terminated()方法后,就会由TIDYING转变为TERMINATED状态。
如何保存线程状态

ThreadPoolExecutor 源码中线程池的运行状态使用 ctl 高3位保存运行状态,低29位保存有效的工作线程数

    private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));private static final int COUNT_BITS = Integer.SIZE - 3;private static final int CAPACITY   = (1 << COUNT_BITS) - 1;// runState is stored in the high-order bitsprivate static final int RUNNING    = -1 << COUNT_BITS;private static final int SHUTDOWN   =  0 << COUNT_BITS;private static final int STOP       =  1 << COUNT_BITS;private static final int TIDYING    =  2 << COUNT_BITS;private static final int TERMINATED =  3 << COUNT_BITS;// Packing and unpacking ctlprivate static int runStateOf(int c)     { return c & ~CAPACITY; }private static int workerCountOf(int c)  { return c & CAPACITY; }private static int ctlOf(int rs, int wc) { return rs | wc; }

COUNT_BITS被定义为Integer.SIZE - 3,即32位整数的29位,每个线程池状态(如RUNNINGSHUTDOWN等)都是通过将一个整数左移COUNT_BITS位来定义的,这样就把状态值放到了整数的最高3位。

例如:

RUNNING状态的值为-1左移29位,-1 的二进制表示为1111 1111 1111 1111 1111 1111 1111 1111,共32个1。

-1 << 29 = 1110 0000 0000 0000 0000 0000 0000 0000,其中高3位是111表示的就是线程池处于 RUNNING状态。

线程池核心参数

  • corePoolSize:核心线程数,空闲了也不会销毁,除非设置了允许销毁核心线程(allowCoreThreadTimeOut)。
  • maximumPoolSize:线程池允许的最大线程数
  • keepAliveTime:当线程数大于核心线程数时,多余空闲的线程在这个时间内还没有等到新任务就会被销毁
  • unit:keepAliveTime的时间单位
  • workQueue:存放还未被线程执行的任务
  • threadFactory:线程工厂,可以自定义设置线程池中线程的线程名称等
  • handler:拒绝策略,但线程池无法执行新增的线程时,是抛弃还是其他策略。
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {if (corePoolSize < 0 ||maximumPoolSize <= 0 ||maximumPoolSize < corePoolSize ||keepAliveTime < 0)throw new IllegalArgumentException();if (workQueue == null || threadFactory == null || handler == null)throw new NullPointerException();this.acc = System.getSecurityManager() == null ?null :AccessController.getContext();this.corePoolSize = corePoolSize;this.maximumPoolSize = maximumPoolSize;this.workQueue = workQueue;this.keepAliveTime = unit.toNanos(keepAliveTime);this.threadFactory = threadFactory;this.handler = handler;}

线程池执行任务流程

  1. 当工作线程数小于核心线程数时,新任务来临,会启动新线程执行任务。
  2. 当工作线程数大于核心线程数且小于最大线程数时,新任务会保存到队列当中等待线程执行。
  3. 当队列满了且核心线程数小于最大线程数时,新任务会创建新线程执行。
  4. 当队列已满且工作线程数达到最大线程数时,线程池会触发拒绝策略由RejectedExecutionHandler处理。
  5. 先线程池中线程数超过核心线程数,空闲时间超过keepAliveTime时,空闲线程会被销毁。

线程池拒绝策略

RejectedExecutionHandler 接口的实现类有四种,所以默认有四种拒绝策略:

**AbortPolicy:**直接抛出异常,阻止系统正常运行。可以根据业务逻辑选择重试或者放弃提交等策略。

**CallerRunsPolicy :**只要线程池未关闭,该策略直接在调用者线程中,运行当前被丢弃的任务。

不会造成任务丢失,同时减缓提交任务的速度,给执行任务缓冲时间。

**DiscardOldestPolicy :**丢弃最老的一个请求,也就是即将被执行的任务,并尝试再次提交当前任务。

**DiscardPolicy :**该策略默默地丢弃无法处理的任务,不予任何处理。如果允许任务丢失,这是最好的一种方案。

Executors提供的几种线程池

  • newSingleThreadExecutor():只有一个线程的线程池,任务是顺序执行,适用于一个一个任务执行的场景
  • newCachedThreadPool():线程池里有很多线程需要同时执行,60s内复用,适用执行很多短期异步的小程序或者负载较轻的服务
  • newFixedThreadPool():拥有固定线程数的线程池,如果没有任务执行,那么线程会一直等待,适用执行长期的任务。
  • newScheduledThreadPool():用来调度即将执行的任务的线程池
  • newWorkStealingPool():底层采用forkjoin的Deque,采用独立的任务队列可以减少竞争同时加快任务处理
参数FixedThreadPoolCachedThreadPoolScheduledThreadPoolSingleThreadExecutorSingleScheduledThreadPool
corePoolSize构造函数传入0构造函数传入11
maxPoolSize同corePoolSizeInteger.MAX_VALUEInteger.MAX_VALUE1Integer.MAX_VALUE
keepAliveTime060s000

建议开发规范

阿里Java开发手册中提到,【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方

式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

Executors 返回的线程池对象的弊端如下:

  1. FixedThreadPool 和 SingleThreadPool:允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。

  2. CachedThreadPool:允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。

  3. ScheduledThreadPool:允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。

根据业务独立配置线程池,将较慢服务与主线程池隔离开。

创建线程池使用线程工厂指定形成名称,方便出错时排查。

线程资源必须由线程池提供,不允许自行在程序中显示创建线程。

相关文章:

Java线程池知识点梳理

Java线程池知识点梳理 什么是线程池&#xff1f; 线程在系统中创建的成本是相对比较高的&#xff0c;所以使用”池化“的思想&#xff0c;设计线程池&#xff0c;有大量任务需要执行时&#xff0c;可以直接从线程池中使用已经创建好的线程直接去执行。减少线程的创建和销毁带…...

SFT、RLHF、DPO、IFT —— LLM 微调的进化之路_如何搭建自己的dpo

TL;DR • SFT、RLHF 和 DPO 都是先估计 LLMs 本身的偏好&#xff0c;再与人类的偏好进行对齐&#xff1b; • SFT 只通过 LLMs 生成的下一个单词进行估计&#xff0c;而 RLHF 和 DPO 通过 LLMs 生成的完整句子进行估计&#xff0c;显然后者的估计会更准确&#xff1b; • 虽然…...

CSS 选择器简单回顾

引言 当我们探讨网页设计和开发时, CSS(层叠样式表) 无疑是一个不可或缺的技术, 它使我们能够精确控制网页的外观和布局, 为用户创造出独特的视觉体验、以及良好的交互体验!! 而一个完整的 CSS 规则则是由两个主要部分组成: 选择器和声明块 那么今天我们就来盘点下常见的几种选…...

uniapp配置微信小程序分包(分包优化)

1.manifest.json中 源码视图中找到mp-weixin&#xff0c;新增代码"optimization":{"subPackages":true}&#xff0c;如下图所示 "optimization" : {"subPackages" : true } 2.pages.json中 分包内静态文件示例 "subPackages&…...

MySQL-10.DML-添加数据insert

一.DML(INSERT) -- DDL&#xff1a;数据操作语言 -- DML&#xff1a;插入数据 - insert -- 1.为tb_emp表的username&#xff0c;name&#xff0c;gender字段插入值 insert into tb_emp (username,name,gender) values (wuji,无忌,1); -- 这样会报错&#xff0c;因为create_ti…...

ARM/Linux嵌入式面经(四八):tp-link联洲国际

文章目录 1. **模电基础**:请解释共射电路的工作原理,并描述如何计算其放大倍数。工作原理放大倍数计算面试官追问及回答2. **DCDC损耗**:有哪些方法可以降低DCDC转换器的损耗?3. **示波器使用**:如何用示波器正确测量DCDC的开关纹波?4. **IIC通信**:IIC通信协议中是否需…...

代码实践篇四 形状检测与规则重建

本节内容主要涉及形状检测&#xff08;Shape Detection&#xff09;与形状重建&#xff08;Shape Reconstruction&#xff09;&#xff0c;具体算法步骤会在后续章节介绍。CGAL在6.0重点更新了形状重建部分的一些模块——动态空间分割与动态形状重建等&#xff0c;也会在后续详…...

JVM(HotSpot):GC之垃圾回收阶段

文章目录 前言一、标记清除算法(Mark Sweep)二、标记整理算法(Mark Compact)三、复制算法(Copy) 前言 标记出垃圾对象之后&#xff0c;就要进行清理。 那么&#xff0c;如何清理&#xff1f; 这里也有相应的算法。 主要有三种。 一、标记清除算法(Mark Sweep) 原理说明&…...

Go 项目如何集成类似mybatisPlus插件呢?GORM走起!!

导读&#xff1a; 在 Go 项目中&#xff0c;虽然没有像 MyBatis Plus 这样特定的 ORM 插件&#xff0c;但可以使用功能相似的 Go ORM 框架&#xff0c;比如 GORM&#xff0c;它支持链式查询、自动迁移、预加载等功能&#xff0c;与 MyBatis Plus 有相似之处。通过一些插件或扩…...

《深度学习》Dlib库 CNN卷积神经网络 人脸识别

目录 一、如何实现CNN人脸识别 1、CNN核心概念 1&#xff09;卷积层 2&#xff09;池化层 3&#xff09;激活函数 4&#xff09;全连接层 2、步骤 1&#xff09;加载预训练的人脸识别模型 2&#xff09;读取图像并检测人脸 3&#xff09;提取人脸特征向量 4&#xf…...

滚雪球学Redis[7.1讲]:Redis实战案例

全文目录&#xff1a; &#x1f389;前言&#x1f6a6;1. 使用Redis实现会话管理在Web应用中使用Redis管理会话会话过期与刷新策略安全性考虑与优化 &#x1f9e9;2. 使用Redis实现缓存系统缓存的基本原理Redis缓存的应用场景缓存失效策略与雪崩预防 ✨3. Redis在排行榜系统中的…...

WordPress外部图片本地化插件

一款用于本地化文章的外部图片的插件&#xff0c;支持如下功能&#xff1a; 文章发布前通过编辑器插件本地化 文章手动发布时自动本地化 文章定时发布时自动本地化 针对已发布的文章批量本地化。 源码下载&#xff1a;https://download.csdn.net/download/m0_66047725/898963…...

Linux基础-shell的简单实现

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 Linux基础-shell的简单实现 收录于专栏[Linux学习] 本专栏旨在分享学习Linux的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 1, 全局变…...

Tomcat日志文件详解及catalina.out日志清理方法

目录 前言1. Tomcat日志文件详解1.1 catalina.out1.2 localhost_access_log1.3 catalina.<date>.log1.4 host-manager.<date>.log 和 manager.<date>.log1.5 localhost.<date>.log 2. catalina.out文件管理与清理方法2.1 为什么不能直接删除catalina.o…...

react 中的hooks中的useState

(1). State Hook让函数组件也可以有state状态, 并进行状态数据的读写操作 (2). 语法: const [xxx, setXxx] React.useState(initValue) (3). useState()说明:参数: 第一次初始化指定的值在内部作缓存返回值: 包含2个元素的数组, 第1个为内部当前状态值, 第2个为更新状态值的…...

STM32学习笔记---DMA

目录 一、什么是DMA 1、DMA是什么 2、DMA的工作流程 3、DMA控制器与外设控制器 二、如何配置DMA 1、DMA框图 2、功能说明 2.1 通道选择 2.2 仲裁器 2.3 源、目标和传输模式 2.4 指针递增 2.5 循环模式 2.6 DMA流控制器和外设流控制器 3、程序设计 三、具体使用DMA…...

Cesium 实战 - 自定义纹理材质 - 立体墙(旋转材质)

Cesium 实战 - 自定义纹理材质 - 立体墙(旋转材质) 核心代码完整代码在线示例Cesium 给实体对象(Entity)提供了很多实用的样式,基本满足普通项目需求; 但是作为 WebGL 引擎,肯定不够丰富,尤其是动态效果样式。 对于实体对象(Entity),可以通过自定义材质,实现各种…...

进程间关系与守护进程

一、进程组 1.1、什么是进程组 提到进程的概念&#xff0c; 其实每一个进程除了有一个进程 ID(PID)之外 还属于一 个进程组。进程组是一个或者多个进程的集合&#xff0c; 一个进程组可以包含多个进程。 每一 个进程组也有一个唯一的进程组 ID(PGID)&#xff0c; 并且这个 PG…...

金山翻译接口逆向

网址&#xff08;加密后&#xff09;&#xff1a;aHR0cHM6Ly93d3cuaWNpYmEuY29tL3RyYW5zbGF0ZQ 文章目录 抓包sign值结果加密 逆向sign值第一步第二步1.2.3. 解密content第一步1.2.3. 抓包 F12 -> 翻译框输入spider -> 点击Fetch/XHR -> 找到接口 index.php? 开头的…...

unified-runtime编译与验证

unified-runtime编译与验证 一.创建容器二.编译unified-runtime三.生成一个cuda ptx kernel四.API测试 unified-runtime编译与验证 一.创建容器 docker run --gpus all --shm-size32g -ti \-e NVIDIA_VISIBLE_DEVICESall --privileged --nethost \--rm -it \-v $PWD:/home \-…...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

渲染学进阶内容——模型

最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

10-Oracle 23 ai Vector Search 概述和参数

一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI&#xff0c;使用客户端或是内部自己搭建集成大模型的终端&#xff0c;加速与大型语言模型&#xff08;LLM&#xff09;的结合&#xff0c;同时使用检索增强生成&#xff08;Retrieval Augmented Generation &#…...

【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error

在前端开发中&#xff0c;JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作&#xff08;如 Promise、async/await 等&#xff09;&#xff0c;开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝&#xff08;r…...

归并排序:分治思想的高效排序

目录 基本原理 流程图解 实现方法 递归实现 非递归实现 演示过程 时间复杂度 基本原理 归并排序(Merge Sort)是一种基于分治思想的排序算法&#xff0c;由约翰冯诺伊曼在1945年提出。其核心思想包括&#xff1a; 分割(Divide)&#xff1a;将待排序数组递归地分成两个子…...

精益数据分析(98/126):电商转化率优化与网站性能的底层逻辑

精益数据分析&#xff08;98/126&#xff09;&#xff1a;电商转化率优化与网站性能的底层逻辑 在电子商务领域&#xff0c;转化率与网站性能是决定商业成败的核心指标。今天&#xff0c;我们将深入解析不同类型电商平台的转化率基准&#xff0c;探讨页面加载速度对用户行为的…...

uniapp获取当前位置和经纬度信息

1.1. 获取当前位置和经纬度信息&#xff08;需要配置高的SDK&#xff09; 调用uni-app官方API中的uni.chooseLocation()&#xff0c;即打开地图选择位置。 <button click"getAddress">获取定位</button> const getAddress () > {uni.chooseLocatio…...