线程池 ThreadPoolExecutor 配置参数详解

news2025/1/18 11:51:30

《开发语言-Java》

在这里插入图片描述

线程池 ThreadPoolExecutor 参数详解

  • 一、引言
  • 二、主要内容
    • 2.1 核心构造函数
    • 2.2 核心线程数
    • 2.3 最大线程数
    • 2.4 空闲线程存活时间
    • 2.5 keepAliveTime 的时间单位
    • 2.6 核心线程在空闲时的回收策略
    • 2.7 工作队列
    • 2.8 线程工厂
    • 2.9 拒绝策略
  • 三、总结

一、引言

提到 Java 线程池,就不得不说 ThreadPoolExecutor,它是 Java 并发包 java.util.concurrent 中的一个类,提供一个高效、稳定、灵活的线程池实现,用于实现多线程并发执行任务,提高应用程序的执行效率。

在《任务执行与Executor框架》中,Huazie 介绍了通过 java.util.concurrent.Executors 中的静态工厂方法来创建线程池,而这个线程池实现就是 ThreadPoolExecutor

ThreadPoolExecutor 提供了一系列参数和配置选项,开发人员可以根据应用的需求来定制线程池的行为。

本篇就将详细介绍线程池 ThreadPoolExecutor 中的各种配置参数。

二、主要内容

注意: 以下涉及代码,均来自 JDK 1.8,其他版本如有出入,请自行查看

2.1 核心构造函数

话不多说,先来查看 ThreadPoolExecutor 的核心构造函数:

在这里插入图片描述

上述构造函数中的 7 个参数就是下面将要重点介绍的线程池 ThreadPoolExecutor 的核心配置参数了。

2.2 核心线程数

private volatile int corePoolSize;

corePoolSize 变量就是 核心线程数,即在没有设置allowCoreThreadTimeOuttrue 的情况下,需要保持存活的最小工作线程数量。

翻看 ThreadPoolExecutorexecute(Runnable command) 方法的源码,如下:

在这里插入图片描述

上述截图代码可以看出: 如果运行的线程数少于核心线程数,则为当前任务启动一个新的核心线程。

调用 addWorker 方法会原子性地检查 runStateworkerCount,从而防止在不应该添加线程时发出错误警报【这时 addWorker 方法会返回 false】。

可以通过 setCorePoolSize(int corePoolSize) 方法来重新设置核心线程数,如下图所示:

在这里插入图片描述

setCorePoolSize 方法将覆盖构造函数中设置的核心线程数。如果新值小于当前值,多余的现有线程将在它们下次变为空闲时被终止。如果新值更大,将根据需要启动新线程来执行任何排队的任务。

2.3 最大线程数

private volatile int maximumPoolSize;

maximumPoolSize 变量就是线程池允许的最大线程数。

可以通过 setMaximumPoolSize(int maximumPoolSize) 方法来重新设置线程池允许的最大线程数,如下图所示:

setMaximumPoolSize 方法将覆盖构造函数中设置的最大线程数。如果新值小于当前值,多余的现有线程将在它们下次变为空闲时被终止。

2.4 空闲线程存活时间

private volatile long keepAliveTime;

keepAliveTime 变量就是空闲线程存活时间【即空闲线程等待工作的超时时间(以纳秒为单位)】。当线程池中的线程数量超过 核心线程数 或者 允许核心线程超时 时,线程将使用此超时时间。否则,它们将无限期地等待新工作。

可以通过 setKeepAliveTime(long time, TimeUnit unit) 方法来重新设置空闲线程存活时间,如下图所示:

在这里插入图片描述

setKeepAliveTime 方法会覆盖在构造函数中设置的空闲线程存活时间。如果当前池中有多于核心数量的线程,在等待这段时间而没有处理任务之后,多余的线程将会被终止。

2.5 keepAliveTime 的时间单位

long keepAliveTime;
TimeUnit unit;
// 空闲线程等待工作的超时时间
this.keepAliveTime = unit.toNanos(keepAliveTime);

TimeUnitjava.util.concurrent 包中的枚举类,用于表示给定粒度单位时间持续时间的类,并提供了一些实用方法来进行单位之间的转换,以及在这些单位中执行定时和延迟操作。TimeUnit 并不维护时间信息,而是帮助组织和使用可能在各种上下文中分别维护的时间表示。纳秒被定义为微秒的千分之一,微秒是毫秒的千分之一,毫秒是秒的千分之一,分钟是六十秒,小时是六十分钟,天是二十四小时。

unit.toNanos 用于将 keepAliveTime 的参数值转换为纳秒值。

另外,在源码注释中有如下一段话:

there is no guarantee that a particular timeout implementation 
will be able to notice the passage of time 
at the same granularity as the given TimeUnit.

翻译中文,大概意思就是:

特定的超时实现可能无法保证能够以与给定TimeUnit相同的粒度来感知时间的流逝。

这怎么来理解呢?

这句话是说,尽管 TimeUnit 允许你以不同的时间单位(如纳秒、微秒、毫秒等)指定超时时间,但实际的超时检测机制可能无法精确地按照这些单位来检测时间的流逝。操作系统和硬件通常有 最小时间片 的概念,即它们能够识别的时间单位的最小粒度。例如,某些系统可能只能精确到毫秒级别,而无法精确到更小的微秒或纳秒级别。这意味着即使请求一个非常短的超时(比如几纳秒),实际的等待时间可能会更长,因为系统无法检测到这么短的时间间隔。此外,线程调度和其他系统级别的延迟也可能影响超时的实际精度。即使指定的超时单位很小,其他因素(如线程切换、系统负载等)也可能导致实际的等待时间超过预期。

2.6 核心线程在空闲时的回收策略

private volatile boolean allowCoreThreadTimeOut;

如果为 false(默认值),即使核心线程处于空闲状态,它们也会保持活动状态。
如果为 true,核心线程会使用 keepAliveTime 来设置等待工作的超时时间。

可以通过 ThreadPoolExecutorallowCoreThreadTimeOut(boolean value) 方法进行设置。

在这里插入图片描述

2.7 工作队列

private final BlockingQueue<Runnable> workQueue;

workQueue 变量就是工作队列,它是一个阻塞队列,用于保存等待执行的任务并将其交给工作线程处理。

阅读相关源码注释中,可以看到如下一段话:

We do not require that workQueue.poll() returning null necessarily means that workQueue.isEmpty(), 
so rely solely on isEmpty to see if the queue is empty (which we must do for example when deciding 
whether to transition from SHUTDOWN to TIDYING). This accommodates special-purpose queues such as 
DelayQueues for which poll() is allowed to return null even if it may later return non-null when delays expire.

中文翻译,大概意思如下:

我们并不要求 workQueue.poll() 返回 null 必然意味着 workQueue.isEmpty(),因此仅依赖 isEmpty 来判断队列是否为空(例如,在决定是否从 SHUTDOWN 状态过渡到 TIDYING 状态时必须这样做)。这样可以适应特殊用途的队列,如 DelayQueue,即使它稍后可能会在延迟过期后返回非空值,但 poll() 也允许返回 null。

那这段注释,又该如何理解呢?

我们知道,当使用队列(如 workQueue)来管理待处理的任务时,通常会有一个或多个工作线程不断地从队列中检索任务来进行处理。poll() 方法通常用于从队列中检索下一个可用的元素,但它的行为可能会根据队列的类型而有所不同:

  • 在某些队列(如普通的 LinkedBlockingQueueArrayBlockingQueue)中,poll() 方法在队列为空时返回 null,表示没有更多的元素可供处理。在这种情况下,如果 poll() 返回 null,那么可以确定队列是空的,因为 poll() 的行为与 isEmpty() 方法的返回值一致。
  • DelayQueue 是一个特殊用途的队列,它允许延迟元素的可用性。在 DelayQueue 中,即使队列中可能还有未到期的元素(即元素还没有准备好被处理),poll() 方法也可能会返回 null。这也就说明 poll() 返回 null 并不一定意味着队列也是空的,因为可能还有未到期的元素在队列中。

2.8 线程工厂

private volatile ThreadFactory threadFactory;

threadFactory 变量就是线程工厂,所有线程都是使用这个工厂创建的(通过 addWorker 方法),默认使用 Executors.defaultThreadFactory() 来创建线程。

在这里插入图片描述
在这里插入图片描述

2.9 拒绝策略

private volatile RejectedExecutionHandler handler;

handler 变量就是 拒绝策略,即当执行过程中饱和或关闭时调用的处理程序。

当阻塞队列已满且无法创建新的线程时,线程池会调用拒绝策略来处理新提交的任务。

Java 线程池提供了几种不同的拒绝策略实现,如

  • AbortPolicy:默认策略,直接抛出 RejectedExecutionException 异常,阻止系统正常运行。
    在这里插入图片描述
    在这里插入图片描述
  • CallerRunsPolicy:只用调用者运行一些任务,如果线程池已满,则将任务回退到调用者执行。
    在这里插入图片描述
  • DiscardOldestPolicy:抛弃最老的任务请求,也就是即将被执行的任务。
    在这里插入图片描述
  • DiscardPolicy:直接丢弃任务,不给予任何处理,也不抛出异常。
    在这里插入图片描述

三、总结

本文 Huazie 基于线程池 ThreadPoolExecutor 的核心构造函数,详细介绍了它的一些关键配置参数。通过本文的介绍,相信大家能够对线程池 ThreadPoolExecutor 的配置参数有了更加清晰的理解,这有助于后续更深入地掌握线程池的运作原理。

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

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

相关文章

VOJ 网页跳转 题解 STL栈

网页跳转 用例输入 10 VISIT https://www.jisuanke.com/course/476 VISIT https://www.taobao.com/ BACK BACK FORWARD FORWARD BACK VISIT https://www.jisuanke.com/course/429 FORWARD BACK用例输出 https://www.jisuanke.com/course/476 https://www.taobao.com/ https…

JavaEE进阶:基础知识

JavaEE&#xff1a;Java企业开发 Web网站的工作流程 ⽬前用户对PC端应⽤的开发结构模式主要分为C/S和B/S结构. CS即Client/Server&#xff08;客户机/服务器&#xff09;结构. 常⻅的C/S架构的应⽤⽐如QQ&#xff0c;CCTALK&#xff0c;各种⽹络游戏 等等&#xff0c;⼀般需…

吴恩达机器学习理论基础—逻辑回归模型

吴恩达机器学习理论基础—逻辑回归模型 说明&#xff1a;逻辑回归解决的是分类问题&#xff1a;例如常见的二分类问题。即得到的输出结果只有两个值的信息。 逻辑回归概念基础 逻辑回归用来解决数据集为0和1的二分类的问题 使用逻辑回归模型来解决对应的问题则需要使用一个函…

在 Ubuntu 12.10 安装 wxPython

安装 wxPython 可以使用 pip 工具&#xff0c;但在 Ubuntu 12.10 上需要首先安装 wxPython 的依赖项。请注意&#xff0c;Ubuntu 12.10 已于2013年终止支持&#xff0c;建议升级到更高版本的 Ubuntu。以下是在 Ubuntu 12.10 上安装 wxPython 的一般步骤&#xff1a; 一、问题背…

【创建型模式】工厂方法模式

一、简单工厂模式 1.1 简单工厂模式概述 简单工厂模式又叫做静态工厂方法模式。 目的&#xff1a;定义一个用于创建对象的接口。实质&#xff1a;由一个工厂类根据传入的参数&#xff0c;动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。 简单工厂模式…

011、Python+fastapi,第一个后台管理项目走向第11步:建立python+fastapi项目,简单测试一下

一、说明 本文章就是记录自己的学习过程&#xff0c;如果有用您可以参考&#xff0c;没用你就略过&#xff0c;没有好与不好之分&#xff0c;今天主要是参考了gitee上的一些项目&#xff0c;一步一步的往后i建立 对于学习来说&#xff0c;如果您有java c等经验&#xff0c;py…

注意力机制基本思想(二)(自注意力机制)

​&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;《深度学习基础知识》 相关专栏&#xff1a; ⚽《机器学习基础知识》 &#x1f3d0;《机器学习项目实战》 &#x1f94e;《深度学习项目实…

河北专升本(c语言各种编程题)

目录 第一类、递归调用 第二类、特殊数字 第三类、多维数组 第四类、字符处理 第五类、数学问题 第六类、排序算法 第七类、循环问题 第八类、进制转换 第九类、实际应用 第十类、图形输出 第一类、递归调用 1.汉诺塔&#xff1a;请输入盘子数&#xff0c;输出盘子移动…

JVM 性能调优命令(jps,jinfo,jstat,jstack,jmap)

常用命令&#xff1a;jps、jinfo、jstat、jstack、jmap jps jps查看java进程及相关信息 jps -l 输出jar包路径&#xff0c;类全名 jps -m 输出main参数 jps -v 输出JVM参数jps命令示例 显示本机的Java虚拟机进程&#xff1a; # jps 15729 jar 92153 Jps 90267 Jstat显示主类…

【QT进阶】Qt Web混合编程之html、 js的简单交互

往期回顾 【QT进阶】Qt Web混合编程之VS2019 CEF的编译与使用&#xff08;图文并茂超详细介绍&#xff09;-CSDN博客【QT进阶】Qt Web混合编程之QWebEngineView基本用法-CSDN博客【QT进阶】Qt Web混合编程之CMake VS2019编译并使用QCefView&#xff08;图文并茂超详细版本&…

Mamba论文笔记

Mamba论文 结合序列建模任务通俗地解释什么是状态空间模型&#xff1f;创新点和贡献 为什么Mamba模型擅长捕获long range dependencies&#xff1f; 结合序列建模任务通俗地解释什么是状态空间模型&#xff1f; 状态空间模型&#xff08;State Space Model, SSM&#xff09;是…

css设置文字撑满盒子

效果如上&#xff1a; <div style"width: 250px;background-color:red;text-align-last:justify;word-break: keep-all;">为中国崛起而读书</div>

Git常见命令行操作和IDEA图形化界面操作

设置Git用户名和标签 在安装完Git以后需要设置用户和签名&#xff0c;至于为什么要设置用户签名可以看一下这篇文章【学了就忘】Git基础 — 11.配置Git用户签名说明 - 简书 (jianshu.com) 基本语法&#xff1a; git config --global user.name 用户名 git config --global u…

漳州不饱和聚酯树脂首次出口非洲

我可以确认&#xff0c;2024年4月中旬左右&#xff0c;漳州新阳科技有限公司制造的不饱和聚酯树脂产品首次出口至非洲市场。这批树脂共计167.2吨&#xff0c;经过漳州市古雷海关的监管放行后&#xff0c;被运往非洲国家阿尔及利亚和莫桑比克。这一举动标志着漳州企业在拓展国际…

深度学习基础之《TensorFlow框架(12)—图片数据》

一、图像基本知识 1、如何转换图片文件 回忆&#xff1a;之前我们在特征抽取中讲过如何将文本处理成数据 思考&#xff1a;如何将图片文件转换成机器学习算法能够处理的数据&#xff1f; 我们经常接触到的图片有两种&#xff0c;一种是黑白图片&#xff08;灰度图&#xff09;…

element-ui form表单自定义label的样式、内容

element-ui form表单自定义label的样式、内容 效果截图 代码 <el-form size"small" :inline"true" label-width"120px"><el-form-item prop"name"><div slot"label"><i style"color: red;"…

数据结构·一篇搞定顺序表!

大家好啊&#xff0c;几日不见&#xff0c;甚是想念&#xff0c;从这一篇文章开始&#xff0c;我们就要进入数据结构了哦&#xff0c;那么我们废话不多说&#xff0c;今天我们一起来搞定顺序表&#xff01;&#xff01;&#xff01; 1. 顺序表概念及结构 顺序表是一种线性结…

自定义数据 微调CLIP (结合paper)

CLIP 是 Contrastive Language-Image Pre-training 的缩写&#xff0c;是一个擅长理解文本和图像之间关系的模型&#xff0c;下面是一个简单的介绍&#xff1a; 优点&#xff1a; CLIP 在零样本学习方面特别强大&#xff0c;它可以&#xff08;用自然语言&#xff09;给出图像…

【文件系统】 F2FS文件系统学习

一、基本介绍 1、F2FS History F2FS&#xff08;Flash Friendly File System&#xff09;是专门为Nand Flash设计的一个日志型文件系统&#xff0c;于2012年12月合入Linux3.8内核&#xff0c;Google也在2018年&#xff08;Android P&#xff09;将其吸收到安卓原生版本中&…

【DL水记】循环神经网络RNN的前世今生,Transformer的崛起,Mamba模型

文章目录 RNN网络简介传统RNN网络结构RNN的分类 长-短期记忆网络 (LSTM)GRU网络横空出世的Transformer网络Self-AttentionVisionTransformer Mamba模型Reference: RNN网络简介 “当人类接触新事物时&#xff0c;他们不会从头开始思考。就像你在阅读这篇文章时&#xff0c;你会根…