【面试实战】# 并发编程之线程池配置实战
1.先了解线程池的几个参数含义
corePoolSize
(核心线程池大小):
- 作用: 指定了线程池维护的核心线程数量,即使这些线程处于空闲状态,它们也不会被回收。
- 用途: 核心线程用于处理长期的任务,保持最低的线程数量,以减少线程的创建和销毁的开销。
maximumPoolSize
(最大线程池大小):
- 作用: 指定了线程池中允许的最大线程数。超过这个数量的线程将不会被创建。
- 用途: 限制了线程池的大小,以防止资源耗尽。
keepAliveTime
(线程空闲时间):
- 作用: 当线程数超过
corePoolSize
时,多余的线程在空闲时间超过指定时间后将会被终止和回收。 - 用途: 用于回收不再需要的线程,降低资源消耗。只对超过
corePoolSize
的线程起作用。
unit
(时间单位):
- 作用: 与
keepAliveTime
一起使用,指定线程空闲时间的时间单位(如秒、毫秒)。 - 用途: 定义
keepAliveTime
的时间单位。
workQueue
(任务队列):
作用: 用于保存等待执行的任务的队列。
用途
: 管理任务的排队和处理方式,不同的队列类型可以影响线程池的行为。
- 常见的队列类型有:
SynchronousQueue
: 不存储任务,任务直接交给线程执行。如果没有空闲线程,则创建新线程。LinkedBlockingQueue
: 无界队列,可以存储任意多的任务。只有在任务队列为空时,才会创建新线程。ArrayBlockingQueue
: 有界队列,存储固定数量的任务,当队列满时,任务将被拒绝。
- 常见的队列类型有:
threadFactory
(线程工厂):
- 作用: 用于创建线程的工厂,可以定制线程的创建,比如设置线程名、优先级等。
- 用途: 统一管理线程的创建细节,有助于调试和监控。
handler
(饱和策略/拒绝策略):
作用: 当任务无法提交给线程池(例如线程池已满且任务队列已满)时,如何处理新任务。
用途
: 定义任务无法被执行时的处理方式。
- 常见策略有:
AbortPolicy
: 抛出RejectedExecutionException
异常。CallerRunsPolicy
: 由调用者线程执行该任务。DiscardPolicy
: 丢弃新提交的任务。DiscardOldestPolicy
: 丢弃队列中最旧的任务。
- 常见策略有:
2.调整线程池配置应对高并发(常规操作)
为了应对高并发的需求,可以考虑以下调整:
- 增大
corePoolSize
和maximumPoolSize
:- 增加核心线程和最大线程数可以提高线程池的并发处理能力,减少任务的等待时间。
- 调整
keepAliveTime
和unit
:- 减少
keepAliveTime
可以更快地回收闲置线程,释放资源。相反,增加keepAliveTime
适用于任务间隔较长的场景,以避免频繁创建和销毁线程。
- 减少
- 选择合适的
workQueue
:- 使用
SynchronousQueue
可以在任务很多但线程数不足时迅速增加线程数。 - 使用
LinkedBlockingQueue
可以应对任务队列过长的问题,但可能导致线程数不会增加到最大。 - 使用
ArrayBlockingQueue
适合在任务数有限的场景,防止资源耗尽。
- 使用
- 合理配置
handler
:- 根据系统需求选择适合的拒绝策略。比如,在希望任务尽量被处理时使用
CallerRunsPolicy
,在任务不能丢失时选择AbortPolicy
。
- 根据系统需求选择适合的拒绝策略。比如,在希望任务尽量被处理时使用
- 优化
threadFactory
:- 使用自定义的线程工厂设置线程名、优先级、守护线程等,提高线程管理的清晰度和系统稳定性。
- 监控和调整:
- 定期监控线程池的性能指标,如任务队列长度、线程使用率等,并根据实际情况动态调整参数配置。
// 创建线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(10, // corePoolSize50, // maximumPoolSize60, // keepAliveTimeTimeUnit.SECONDS, // keepAliveTime's unitnew LinkedBlockingQueue<>(100), // workQueueExecutors.defaultThreadFactory(), // threadFactorynew ThreadPoolExecutor.AbortPolicy() // handler
);// 提交任务
executor.submit(() -> {// Task implementation
});// 关闭线程池
executor.shutdown();
3.IO密集型、CPU密集型任务的合理配置(生产常用)
3.1 IO密集型任务
IO密集型任务:(例如网络操作、文件读写)通常不需要大量的CPU时间,但可能会等待IO操作的完成。为了有效利用系统资源,可以配置
更多
的线程来掩盖IO操作的等待时间。
配置建议:
corePoolSize
和maximumPoolSize
:- 建议的线程数通常远超过 CPU 核心数,因为线程在等待IO操作时不会占用CPU。可以使用
(CPU 核心数 * 2)
或更多,甚至是(CPU 核心数 * 2) + 1
这种经验值。 - 如果线程数太少,CPU资源可能未能充分利用。太多的线程可能会导致线程上下文切换的开销。
- 建议的线程数通常远超过 CPU 核心数,因为线程在等待IO操作时不会占用CPU。可以使用
keepAliveTime
和unit
:- 适当地增加
keepAliveTime
,让线程在空闲时保留一段时间,以便在短时间内有任务到达时无需重新创建线程。
- 适当地增加
workQueue
:LinkedBlockingQueue
是常见选择,因为它可以有效处理大量任务,而不需要频繁地创建和销毁线程。SynchronousQueue
也可以用于高并发IO场景,确保任务直接交给线程执行,迅速响应。
示例:
int numCores = Runtime.getRuntime().availableProcessors();
ThreadPoolExecutor ioBoundExecutor = new ThreadPoolExecutor(numCores * 2, // corePoolSizenumCores * 2 + 1, // maximumPoolSize60L, // keepAliveTimeTimeUnit.SECONDS, // keepAliveTime's unitnew LinkedBlockingQueue<>(), // workQueueExecutors.defaultThreadFactory(), // threadFactorynew ThreadPoolExecutor.CallerRunsPolicy() // handler
);
3.2 CPU密集型任务
CPU密集型任务:(例如计算密集的操作、数据处理)主要消耗
CPU 资源
,因此线程数应该与 CPU 核心数相匹配,以避免过度的线程上下文切换和资源竞争。
配置建议:
corePoolSize
和maximumPoolSize
:- 通常设置为
CPU 核心数
或CPU 核心数 + 1
。 - 过多的线程可能导致频繁的上下文切换,降低性能。
- 通常设置为
keepAliveTime
和unit
:keepAliveTime
通常设置较短,适合及时回收空闲线程。
workQueue
:SynchronousQueue
或ArrayBlockingQueue
是不错的选择,可以避免任务堆积,确保线程数控制在合理范围内。
示例:
int numCores = Runtime.getRuntime().availableProcessors();
ThreadPoolExecutor cpuBoundExecutor = new ThreadPoolExecutor(numCores, // corePoolSizenumCores + 1, // maximumPoolSize30L, // keepAliveTimeTimeUnit.SECONDS, // keepAliveTime's unitnew SynchronousQueue<>(), // workQueueExecutors.defaultThreadFactory(), // threadFactorynew ThreadPoolExecutor.AbortPolicy() // handler
);
3.3 关键考虑因素
- 系统资源和负载:
- 监控系统的实际负载和资源使用情况,定期调整配置。
- 任务特性:
- 根据任务的性质(长任务、短任务、IO 密集型、CPU 密集型)选择合适的线程池配置。
- 阻塞时间:
- 对于 IO 密集型任务,理解和分析任务的阻塞时间,并根据其阻塞时间设置合适的线程池大小。
- 拒绝策略:
- 合理选择拒绝策略(如
AbortPolicy
,CallerRunsPolicy
),确保系统在负载过高时能平稳处理任务。
- 合理选择拒绝策略(如
4.专业级线程池配置(大厂规范)
4.1 线程池大小的计算公式
IO 密集型任务
对于IO密集型任务,可以使用以下公式计算适合的线程池大小:
N_threads
: 推荐的线程池大小N_cores
: CPU核心数W
: 任务的等待时间(包括IO操作的等待时间)C
: 任务的计算时间U
: 期望的CPU使用率,通常设为0.8~0.9,避免CPU负载过高(0 < U < 1)解释: 公式中的 W/C反映了IO操作占用的时间比,
1 - U
是为了预留一定的CPU资源。
示例:
假设有一个任务,CPU核心数为8,IO等待时间为200ms,计算时间为100ms,期望的CPU使用率为80%,则推荐的线程池大小为:
这意味着你可能需要配置大约120个线程来处理IO密集型任务。
CPU 密集型任务
对于CPU密集型任务,线程池的大小通常可以通过以下公式估算:
在CPU密集型场景下,由于
W
很小或接近于零,因此公式通常简化为:
示例:
假设有一个任务,CPU核心数为8,计算时间大部分占用时间,等待时间可以忽略不计,则推荐的线程池大小为:
5.根据TPS和QPS进行线程池计算(生产常用)
其实和4的公式差不多
5.1 基础概念:
TPS (Transactions Per Second)
: 每秒系统处理的事务
数量。这通常用于描述系统处理更复杂的业务逻辑的能力。QPS (Queries Per Second)
: 每秒系统处理的查询
数量,通常用于衡量服务端API或数据库的查询处理能力。响应时间
: 单个请求或事务的平均处理时间。
5.2 公式:
N_threads
: 推荐的线程池大小Q
: 每秒的请求数(TPS 或 QPS)R
: 平均响应时间(秒)U
: 系统期望的CPU利用率(< 1, 通常为80%~90%)
解释: 公式描述了在满足特定吞吐量和响应时间的情况下,需要的线程数,预留了一部分CPU资源以防过载。
5.3 IO密集型、CPU密集型任务选择
这里我们主要举例说明IO密集型任务
因为:
CPU密集型
任务主要消耗CPU资源,线程数接近CPU核心数就足够,可以加一个额外的线程来处理。Nthreads=Ncores+1
IO密集型:
公式:
说明: 由于IO密集型任务在等待IO时不会占用CPU,因此线程数可以较高,适用于处理高并发的IO操作。
示例:
假设系统需要处理每秒500个请求(Q = 500),每个请求的平均响应时间为0.2秒,系统期望的CPU利用率为80%(U = 0.8):
这意味着你可能需要大约500个线程来处理这些IO密集型请求。
示例代码:
int qps = 500;
double responseTime = 0.2;
double targetUtilization = 0.8;int nThreads = (int) (qps * responseTime / (1 - targetUtilization));ThreadPoolExecutor ioBoundExecutor = new ThreadPoolExecutor(nThreads, // corePoolSizenThreads, // maximumPoolSize60L, // keepAliveTimeTimeUnit.SECONDS, // keepAliveTime's unitnew LinkedBlockingQueue<>(), // workQueueExecutors.defaultThreadFactory(), // threadFactorynew ThreadPoolExecutor.CallerRunsPolicy() // handler
);
6.总结
- IO密集型任务: 使用公式 计算线程池大小。
- CPU密集型任务: 使用公式 计算线程池大小。
- 混合型任务: 综合IO和CPU的公式进行计算和调整。
-
W
: 平均等待时间C
: 平均计算时间
- 实际应用: 根据QPS或TPS、响应时间、期望的CPU利用率等参数进行计算,并定期监控系统负载进行调整。
合理的线程池配置可以显著提升系统的处理能力和资源利用率,因此根据具体需求和系统指标进行精细配置是至关重要的。
相关文章:
【面试实战】# 并发编程之线程池配置实战
1.先了解线程池的几个参数含义 corePoolSize (核心线程池大小): 作用: 指定了线程池维护的核心线程数量,即使这些线程处于空闲状态,它们也不会被回收。用途: 核心线程用于处理长期的任务,保持最低的线程数量,以减少线程的创建和…...
Pytest 读取excel文件参数化应用
本文是基于Pytest框架,读取excel中的文件,传入页面表单中,并做相应的断言实现。 1、编辑媒体需求 首先明确一下需求,我们需要对媒体的表单数据进行编辑,步骤如下: 具体表单如下图所示 1、登录 2、点击我…...
qt 一个可以拖拽的矩形
1.概要 2.代码 2.1 mycotrl.h #ifndef MYCOTRL_H #define MYCOTRL_H#include <QWidget> #include <QMouseEvent>class MyCotrl: public QWidget {Q_OBJECT public://MyCotrl();MyCotrl(QWidget *parent nullptr); protected:void paintEvent(QPaintEvent *even…...
C# 启动exe 程序
(1) publicbool Start () System.Diagnostics.Process process new System.Diagnostics.Process(); process.StartInfo.FileName "iexplore.exe"; //IE浏览器,可以更换 process.StartInfo.Arguments "http://www.baidu.com"; process.…...
Netty中的Reactor模型实现
Netty版本:4.1.17 Reactor模型是Doug Lea在《Scalable IO in Java》提出的,主要是针对NIO的。 其中的主从Reactor模式在Netty中的配置如下: EventLoopGroup bossGroup new NioEventLoopGroup(1); EventLoopGroup workerGroup new NioEv…...
dll丢失应该怎么解决,总结5种解决DLL丢失问题的方法
在数字时代,我们与计算机的每一天都密不可分。然而,就像所有技术产品一样,我们的计算设备也时不时地会出现一些问题,让人头疼不已。就在上周,我遭遇了一个令人崩溃的技术挑战——DLL文件丢失。这个看似微不足道的小问题…...
dial tcp 10.96.0.1:443: connect: no route to host
1、创建Pod一直不成功,执行kubectl describe pod runtime-java-c8b465b98-47m82 查看报错 Warning FailedCreatePodSandBox 2m17s kubelet Failed to create pod sandbox: rpc error: code Unknown desc failed to setup network for…...
VScode创建ROS项目 ROS集成开发环境
ROS使用VScode创建项目步骤 1.创建ROS工作空间2.启动VScode3.VScode编译ROS4.创建ROS功能包C语言开发Python语言开发 本文章介绍了如何在Ubuntu18.04系统下搭建VScode 的ROS项目 搭建项目分为一下几个步骤: 1.创建ROS工作空间 创建一个demo的ROS工作空间࿰…...
nodejs从基础到实战学习笔记-nodejs简介
一、Node.js简介 • Node.js是一个能够在服务器端运行JavaScript的开放源代码、跨平台JavaScript运行环境。 • Node采用Google开发的V8引擎运行js代码,使用事件驱动、非阻塞和异步I/O模型等技术来提高性能,可优化应用程序的传输量和规模。 1.1 特性 …...
2024年最新版------二进制安装部署Kubernetes(K8S)集群
Kubernetes二进制集群部署 文章目录 Kubernetes二进制集群部署资源列表基础环境一、环境准备1.1、绑定映射关系1.2、所有主机安装Docker1.3、所有主机设置iptables防火墙 二、生成通信加密证书2.1、master上成功CA证书2.2.1、创建证书存放位置并安装证书生成工具2.2.2、拷贝证书…...
【mysql】关键词搜索实现
关键词搜索实现两种方式 -- 方式1 模糊匹配搜索 -- 场景一:搜索出来地址内包含‘李’和‘中国’的 select * from tn_md_cust_link where address like concat (%李%) or address like concat (%中国%) -- 场景二:搜索地址或者名称包含 ‘181’ 的 …...
Python面试十问2
一、如何使用列表创建⼀个DataFrame # 导入pandas库 import pandas as pd# 创建一个列表,其中包含数据 data [[A, 1], [B, 2], [C, 3]]# 使用pandas的DataFrame()函数将列表转换为DataFrame df pd.DataFrame(data, columns[Letter, Number]) # 列名# 显示创建的…...
C# OpenCvSharp 图像处理函数-颜色通道-cvtColor
使用 OpenCvSharp 中的 cvtColor 函数进行图像颜色转换 在图像处理领域,颜色空间转换是一个非常常见的操作。OpenCvSharp 提供了一个强大的函数 cvtColor 来处理这类转换。本文将详细介绍 cvtColor 函数的使用方法,并通过具体的示例演示如何在实际项目中应用这些知识。 函数…...
总结之LangChain(三)——模型IO缓存
一、聊天模型缓存 LangChain为聊天模型提供了一个可选的缓存层。这有两个好处: 如果您经常多次请求相同的完成结果,它可以通过减少您对LLM提供程序的API调用次数来帮您节省费用。 它可以通过减少您对LLM提供程序的API调用次数来加快您的应用程序速度。…...
判断一个Java服务是不是GateWay
方法 直接在对应服务的url后变加上后缀/actuator/gateway/routes,看是否会返回Gateway的路由信息。 如果返回了GateWay的路由列表,则该服务为Gateway服务。...
三次插值曲线--插值技术
三次插值曲线 1.1.三次样条曲线 三次样条曲线的基本思想是,在给定的一系列点(称为控制点或数据点)之间,通过一系列三次多项式曲线段来拟合这些点,使得整个曲线既平滑又准确地通过所有控制点。 1.1.1.数学定义 给定…...
python循环结构
1.while 循环 语句: while 循环条件表达式: 代码块 else: 代码块 小练: 设计一百以内的偶数相加 n 0 while n < 100:n 1if n % 2 0 :print(n) 判断是不是闰年(四年一润和百年不润,或者四百年一润&am…...
深入理解Netty的Pipeline机制:原理与实践详解
深入理解Netty的Pipeline机制:原理与实践详解 Netty是一个基于Java的高性能异步事件驱动的网络应用框架,广泛应用于高并发网络编程。(学习netty请参考:深入浅出Netty:高性能网络应用框架的原理与实践)Nett…...
直方图均衡化示例
禹晶、肖创柏、廖庆敏《数字图像处理(面向新工科的电工电子信息基础课程系列教材)》 图3-17...
私域电商新纪元:消费增值模式的创新与成功实践
大家好,我是吴军,很高兴能够与您分享私域电商领域的魅力与机遇。今天,我将为大家呈现一个令人瞩目的成功案例,这个案例充分展现了私域电商的巨大潜力和无限可能。 在短短一个月的时间里,我们的客户成功实现了业绩的飞跃…...
Java——IO流(一)-(6/8):字节流-FileInputStream 每次读取多个字节(示例演示)、一次读取完全部字节(方式一、方式二,注意事项)
目录 文件字节输入流:每次读取多个字节 实例演示 注意事项 文件字节输入流:一次读取完全部字节 方式一 方式二 注意事项 文件字节输入流:每次读取多个字节 用到之前介绍过的常用方法: 实例演示 需求:用每次读取…...
服务器SSH 免密码登录
1. 背景 为了服务器的安全着想,设置的服务器密钥非常长。但是这导致每次连接服务器都需要输入一长串的密码,把人折腾的很痛苦,所以我就在想,能不能在终端SSH的时候无需输入密码。 windows 可以使用 xshell 软件,会自…...
Linux安装MySQL以及远程连接
1、Linux安装MySQL 1.1、准备解压包 MySQL5.x解压包 提取码:9y7n 1.2、通过rpm脚本安装 切记安装顺序:common --> libs --> client --> server 因为它们之间存在依赖关系,所以务必按照顺序安装 安装前请确保当前目录/文…...
SQL Server 数据库分页技术详解:选择最佳方法优化查询性能”。
当今数据驱动的应用程序中,数据库分页技术在优化查询性能和提升用户体验中扮演着重要角色。在 SQL Server 环境下,开发者面对大数据集时,常常需要选择合适的分页方法以平衡功能需求和性能优化。本文将详细介绍 SQL Server 中几种主要的分页技…...
electron录制-镜头缩放、移动
要求 1、当录屏过程中,鼠标点击,镜头应该往点击处拉近,等一段时间还原 2、录屏过程中,可能会发生多次点击,但是点击位置偏差大,可能会导致缩放之后,画面没出来,因此需要移动镜头帧 …...
红队内网攻防渗透:内网渗透之内网对抗:信息收集篇自动项目本机导出外部打点域内通讯PillagerBloodHound
红队内网攻防渗透 1. 内网自动化信息收集1.1 本机凭据收集类1.1.1、HackBrowserData 快速获取浏览器的账户密码1.1.2、Searchall 快速搜索服务器中的有关敏感信息还有浏览器的账户密码1.1.3、Pillager 适用于后渗透期间的信息收集工具,可以收集目标机器上敏感信息1.2 对外打点…...
2024最新IDEA插件开发+发布全流程 SelectCamelWords[选中驼峰单词](idea源代码)
2024最新IDEA插件开发(发布)-SelectCamelWords[选中驼峰单词](idea源代码) 参考文档 Jetbrains Idea插件开发文档: https://plugins.jetbrains.com/docs/intellij/welcome.html代码地址:https://github.com/yangfeng…...
【网络安全】网络安全基础精讲 - 网络安全入门第一篇
目录 一、网络安全基础 1.1网络安全定义 1.2网络系统安全 1.3网络信息安全 1.4网络安全的威胁 1.5网络安全的特征 二、入侵方式 2.1黑客 2.1.1黑客入侵方式 2.1.2系统的威胁 2.2 IP欺骗 2.2.1 TCP等IP欺骗 2.2.2 IP欺骗可行的原因 2.3 Sniffer探测 2.4端口扫描技术…...
初识 GPT-4 和 ChatGPT
文章目录 LLM 概述理解 Transformer 架构及其在 LLM 中的作用解密 GPT 模型的标记化和预测步骤 想象这样⼀个世界:在这个世界里,你可以像和朋友聊天⼀样快速地与计算机交互。那会是怎样的体验?你可以创造出什么样的应用程序?这正是…...
【C语言】解决C语言报错:Array Index Out of Bounds
文章目录 简介什么是Array Index Out of BoundsArray Index Out of Bounds的常见原因如何检测和调试Array Index Out of Bounds解决Array Index Out of Bounds的最佳实践详细实例解析示例1:访问负索引示例2:访问超出上限的索引示例3:循环边界…...
凡科网站建设如何植入代码/在线企业管理培训课程
托盘显示许多软件都有这个功能,在C#中如何实现呢,下面的方法可以实现托盘显示,不过可能有些复杂。 首先,需要在工具栏拖入NotifyIcon,如图1的那个控件。 图一: 然后,设置NotifyIcon的属性&…...
wordpress用户登录显示请求失败/google浏览器官方下载
Scala数据交互 Scala使用一种函数式的方式来处理数据交互,包括入参及返回值。 Option: 解决null(空指针)问题Either: 解决返回值不确定(返回两个值的其中一个)问题Try: 解决函数可能会抛出异常问题 Option/Some/None的…...
网站建设评标办法/重庆关键词seo排名
转载https://blog.csdn.net/gesanghua601/article/details/85131156 最近经常利用wireshark抓包,查看数据包的数据,遇到一二问题总结下,也分享给遇到同样问题的小伙伴儿~~ 抓包rtp难以直观看到裸码流格式数据,进而难以判断码流类…...
中国室内设计师网官网/如何提升网站seo排名
链接:http://arc073.contest.atcoder.jp/tasks/arc073_c 题目大意:给定n对数,将每对中一个染红一个染蓝,求(Rmax-Rmin)*(Bmax-Bmin)。 分析:- -感觉没有太多的知识点&…...
佛山新网站制作渠道/信息流广告代运营
今日头条视频去重复上传方法-网络营销推广教程如何完美去除视频字幕和LOGO批量下载快手西瓜视频如何快速去掉视频上的logo批量下载快手西瓜视频还有很多渠道也可以上传视频,比如微信公众号、AcFun、百度视频、凤凰自媒体、qq公众平台等等,但是这些平台基…...
程序开发需要学什么/seo培训机构
https://blog.csdn.net/lizhihua0925/article/details/52595813blog.csdn.net最近在研究Docker,正好也想学习一下Laravel,但每次laravel的部署很麻烦,所以正在研究了一下,做一下Docker镜像,感觉棒棒的~~~Dockerfilel…...