线程池 ThreadPoolExecutor 配置参数详解

《开发语言-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 的配置参数有了更加清晰的理解,这有助于后续更深入地掌握线程池的运作原理。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

密码学 | 承诺:基本概念

目录 正文 1 承诺的交互 2 承诺的属性 3 硬币抛掷问题 3.1 朴素版方案 3.2 承诺版方案 &#x1f951;源自&#xff1a;https://en.wikipedia.org/wiki/Commitment_scheme &#x1f951;写在前面&#xff1a;英文的承诺是 commitment scheme&#xff0c;否则很难进行…

项目实践---贪吃蛇游戏(游戏的概述)

这里要准备三个文件&#xff1a;1.头文件&#xff08;snake.h&#xff09; 2.测试文件&#xff08;test.c&#xff09; 3.主文件&#xff08;snake.c&#xff09; 贪吃蛇游戏是一个经典的C语言代码实现的项目&#xff0c;大约500行代码。对于大家来说&#xff0c;贪吃蛇都玩过…

如何用个人电脑搭建一台本地服务器,并部署项目到服务器详细教程

服务器是一种高性能计算机&#xff0c;作为网络的节点&#xff0c;它存储、处理网络上80%的数据、信息&#xff0c;因此也被称为网络的灵魂。与普通计算机相比&#xff0c;服务器具有高速CPU运算能力、长时间可靠运行、强大I/O外部数据吞吐能力以及更好的扩展性。 服务器的主要…

【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;图文并茂超详细版本&…

NSSCTF Round#22 Reverse个人专项赛 WP

1. ezcrypt&#xff08;史&#xff09; pyinstxtractor.py解包exe&#xff0c;然后pycdc反编译NSSCTF.pyc 得到的源码并不完整&#xff0c;但是重要的部分已经有了&#xff0c;就是一个blowfish加密 但是密钥是crypto.SomeEncode&#xff0c;这并不是字面意义的字符串&#x…

基于弹簧鞘复合纱和迁移学习算法的可穿戴人体重构和智能试衣系统

研究背景 在信息时代和元宇宙的背景下&#xff0c;虚拟服装设计对满足服装行业的个性化需求至关重要。与传统方法不同&#xff0c;虚拟试衣节省时间、方便客户&#xff0c;并提供多样化的款式。准确得测量人体围度并重构出人体的模型是虚拟试衣的关键。为了实现动态人体重构&a…

路径规划 | RRT结合APF算法快速探索随机树结合人工势场法的路径规划算法(Matlab)

目录 效果一览基本介绍程序设计参考文献 效果一览 基本介绍 RRT结合APF算法的matlab代码。地图为可以替换的栅格地图。代码是在复现华中科技大学发表的英文论文的基础上的进一步改进。RRT算法。人工势场算法。 1.原论文方法简介&#xff1a;针对快速探索随机树&#xff08;RRT&…

用 Pytorch 训练一个 Transformer模型

昨天说了一下Transformer架构&#xff0c;今天我们来看看怎么 Pytorch 训练一个Transormer模型&#xff0c;真实训练一个模型是个庞大工程&#xff0c;准备数据、准备硬件等等&#xff0c;我只是做一个简单的实现。因为只是做实验&#xff0c;本地用 CPU 也可以运行。 本文包含…

C++ STL 容器 vector

目录 1. vector 对象2. vector 大小 size 和 容量 capacity3. vector 成员函数3.1 迭代器3.2 容量3.3 元素访问3.4 插入3.5 删除3.6 动态扩充与收缩 4. vector 迭代器失效问题总结其他补充 本文测试环境为 编译器 gcc 13.1 vector 是 STL 中的一个顺序容器&#xff0c;它给我们…

如何将静态网页资源“打包“成.exe或者.apk

Hello , 我是小恒不会java。最近有音乐播放器win桌面应用程序的需求&#xff0c;那就说说上手electron 又想到很多人对apk文件不太了解&#xff0c;apk文件就是安卓桌面应用程序&#xff0c;比如你手机现在打开的微信 当然&#xff0c;exe文件基本都清楚&#xff0c;windows可执…

正则表达式(Regular Expression)

正则表达式很重要&#xff0c;是一个合格攻城狮的必备利器&#xff0c;必须要学会&#xff01;&#xff01;&#xff01; &#xff08;参考视频&#xff09;10分钟快速掌握正则表达式&#xff08;奇乐编程学院&#xff09;https://www.bilibili.com/video/BV1da4y1p7iZ在线测试…

React Hooks(常用)笔记

一、useState&#xff08;保存组件状态&#xff09; 1、基本使用 import { useState } from react;function Example() {const [initialState, setInitialState] useState(default); } useState(保存组件状态) &#xff1a;React hooks是function组件(无状态组件) &#xf…

再拓信创版图-Smartbi 与东方国信数据库完成兼容适配认证

近日&#xff0c;思迈特商业智能与数据分析软件 [简称&#xff1a;Smartbi Insight] V11与北京东方国信科技股份有限公司 &#xff08;以下简称东方国信&#xff09;CirroData-OLAP分布式数据库V2.14.1完成兼容性测试。经双方严格测试&#xff0c;两款产品能够达到通用兼容性要…

浪潮信息成功打造大规模、高性能、高可靠的单存储集群方案!

为帮助企业应对商业智能应用中面临的关于海量数据存储及实时分析的难题&#xff0c;浪潮信息日前通过技术研发&#xff0c;创新推出全球首个SAP HANA集群方案&#xff0c;该方案实现了最大可支持HANA集群服务器节点数量的翻倍&#xff0c;单存储即可支持16节点的&#xff0c;大…

图片高效批量管理,一键批量旋转150度,高效整理您的图片库

在数字化时代&#xff0c;我们的生活中充满了各种图片。从手机拍照到网络下载&#xff0c;从社交媒体到工作文档&#xff0c;图片无处不在。然而&#xff0c;随着图片数量的不断增加&#xff0c;如何高效管理这些图片&#xff0c;让它们有序、易于查找&#xff0c;成为了许多人…

Vue3从入门到实战:深度了解相关API

shallowRef 作用&#xff1a;创建一个响应式数据&#xff0c;但只对顶层属性进行响应式处理。 用法&#xff1a; let myVar shallowRef(initialValue); 特点&#xff1a;只跟踪引用值的变化&#xff0c;不关心值内部的属性变化。 shallowReactive 作用&#xff1a;创建一个…

【MySQL】表的基本约束

文章目录 1、约束类型1.1NOT NULL约束1.2UNIQUE&#xff1a;唯一约束1.3DEFAULT&#xff1a;默认值约束1.4PRIMARY KEY&#xff1a;主键约束1.5FOREIGN KEY&#xff1a;外键约束 2、表的设计2.1一对一2.2一对多2.3多对多 1、约束类型 关键字解释NOT NULL指示某列不能存储NULL值…

点赞列表查询列表

点赞列表查询列表 BlogController GetMapping("/likes/{id}") public Result queryBlogLikes(PathVariable("id") Long id) {return blogService.queryBlogLikes(id); }BlogService Override public Result queryBlogLikes(Long id) {String key BLOG_…

【C++航海王:追寻罗杰的编程之路】C++11(上)

目录 1 -> C11简介 2 -> 统一的列表初始化 2.1 -> {}初始化 2.2 -> std::initializer_list 3 -> 声明 3.1 -> auto 3.2 -> decltype 3.3 -> nullptr 1 -> C11简介 在2003年C标准委员会曾经提交了一份技术勘误表(简称TC1)&#xff0c;使得C…

Debian

文章目录 前言一、使用root用户操作二、配置用户使用sudo命令三、添加桌面图标显示1.打开终端2.执行安装命令3.执行成功后重启4. 打开扩展&#xff0c;配置图标 四、图形化界面关闭和打开五、设置静态IP1.查询自己系统网络接口2.修改网络配置文件 总结 前言 Debian 系统在安装…