ThreadPool-线程池使用及原理

1. 线程池使用方式

示例代码:

// 一池N线程
Executors.newFixedThreadPool(int)
// 一个任务一个任务执行,一池一线程
Executors.newSingleThreadExecutorO
// 线程池根据需求创建线程,可扩容,遇强则强
Executors.newCachedThreadPool()
// 自定义线程池方式
new ThreadPoolExecutor(...)

注:一般在工作中都是根据业务场景进行自定义线程池,进行使用;
自定义线程池方法;详见后面章节:自定义线程池

2. 线程池底层工作原理

a. 线程池参数:

线程池,具有多个参数:具有各自的含义:

七参数:

  • corePoolSize:核心线程数,一直保持活跃状态的线程
  • maximumPoolSize:最大线程数,线程池能容纳的最大线程数量
  • keepAliveTime:空闲线程存活时间,非核心线程的空闲存活时间
  • unit:存活的时间单位,非核心线程的空闲存活时间单位
  • workQueue:存放未执行任务的队列
  • threadFactory:线程工厂,创建线程的工厂类
  • handler:拒绝策略,队列满了和达到最大线程数后的拒绝策略

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

b. 线程池的拒绝策略

AbortPolicy:默认,直接抛出RejectedExcutionException异常,阻止系统正常运行
CallerRunsPolicy:该策略既不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用者
DiscardPolicy:直接丢弃任务,不予任何处理也不抛出异常,如果允许任务丢失,这是一种好方案
DiscardOldestPolicy:抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务

c. 线程池底层工作原理

  1. 在创建了线程池后,如果设置了核心线程数(corePoolSize),则线程池中的线程数会先创建相应数量的核心线程。如果没有任务到达,这些核心线程会保持活动状态。

  2. 当调用execute()方法添加一个请求任务时,线程池会根据以下判断来决定任务的执行方式:

    • 如果正在运行的线程数量小于核心线程数(corePoolSize),则会立即使用核心线程来执行任务。
    • 如果正在运行的线程数量大于或等于核心线程数,但任务队列未满,则任务会被放入队列中等待执行。
    • 如果队列已满且正在运行的线程数量小于最大线程数(maximumPoolSize),则会创建非核心线程来执行任务。
      • 这里需要注意,是先执行新的任务,队列里的任务不会执行,详见:5. 注意事项
    • 如果队列已满且正在运行的线程数量已达到最大线程数,且拒绝策略允许,那么线程池会启动拒绝策略来处理新任务。
  3. 当一个线程完成任务时,它会从队列中取下一个任务来执行,或者在没有任务的情况下进入等待状态。

  4. 当一个线程空闲时间超过设定的keepAliveTime时,线程池会根据以下判断来决定线程的命运:

    • 如果当前运行的线程数大于核心线程数(corePoolSize),则空闲线程会被终止。
    • 线程池的所有任务完成后,它最终会收缩到核心线程数的大小。
  5. 注意事项:

    在Java中java.util.concurrent.ThreadPoolExecutor线程池的默认行为是,当任务队列已满且再来一个新任务时,创建的新线程会被用来执行新来的任务而不是队列里已有的任务。

  6. 线程工作原理示意图:

    • 在这里插入图片描述

3. 自定义线程池

a. 介绍:

前面提到过,一般在工作中都是根据业务场景进行自定义线程池;西面是阿里巴巴开发手册的说明;
在这里插入图片描述

b. 实现:

实现代码如下:

import org.jetbrains.annotations.NotNull;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.concurrent.*;/*** @author xxx* @version 1.0* @date xxx*/@Configuration
public class ThreadPoolExecutorConfig {@Beanpublic ThreadPoolExecutor threadPoolExecutor() {// 创建自定义线程池int corePoolSize = 2; // 核心线程数int maxPoolSize = 4; // 最大线程数long keepAliveTime = 10; // 线程空闲时间TimeUnit unit = TimeUnit.SECONDS; // 时间单位BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(10); // 任务队列ThreadFactory threadFactory = Executors.defaultThreadFactory(); // 线程工厂RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy(); // 拒绝策略// 创建ThreadPoolExecutor对象ThreadPoolExecutor threadPool = new ThreadPoolExecutor(corePoolSize,maxPoolSize,keepAliveTime,unit,workQueue,threadFactory,handler);return threadPool;}
}

4. 线程池参数的选择原则

仅供参考:具体的线程池参数,需要根据业务场景,进行合理的测试选择

一般原则:

在使用java.util.concurrent.ThreadPoolExecutor自定义线程池时,参数的设置需要根据具体的业务场景和需求进行调整。以下是一些常用的业务场景和设置原则:

  • 短时任务场景:
    corePoolSize (n+1):可以设置较小的值,例如CPU核心数加1。
    maximumPoolSize (2n):根据系统负载情况和任务的短时性来设置。通常可以设置为核心线程数的两倍或者根据系统资源进行调整。
    workQueue:可以选择容量较小的队列,例如SynchronousQueue,以避免任务积压。

  • 长时任务场景:
    corePoolSize:可以设置为一个相对较大的值,以确保有足够的线程处理任务。
    maximumPoolSize:根据系统负载和任务的长时性来设置。如果长时任务较多,可以将最大线程数设置得较大一些。
    keepAliveTime 和 TimeUnit:根据任务的处理时长和系统的响应时间来设置空闲线程的存活时间。

  • I/O密集型任务场景:
    corePoolSize(2n):可以设置为较大的值,以充分利用系统资源,加速I/O操作。
    maximumPoolSize:根据系统负载和I/O操作的并发数来设置,可以设置得比较大以应对高并发的情况。
    workQueue:可以选择一个适当大小的队列,以充分缓冲I/O任务,但不至于占用过多内存。

  • CPU密集型任务场景:
    corePoolSize:可以根据CPU核心数设置,以充分利用系统的多核处理能力。
    maximumPoolSize:可以设置得比较大,以应对突发的CPU密集型任务,但不要超过系统负载的承受范围。
    workQueue:选择一个合适大小的队列来缓冲任务,避免因任务积压导致性能下降。

设置原则:

要根据具体的业务需求和系统特点来选择参数。
要根据实际情况进行监控和调优,以确保线程池能够有效地处理任务并保持系统的稳定性和性能。
要平衡资源的利用和系统的响应能力,避免设置过大或过小的参数,导致资源浪费或性能问题。

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

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

相关文章

php数组算法(2)字符串转数组后替换指定元素

php中&#xff0c;如何替换字符串“name1,name2,name3”中的name2&#xff0c;输出“name1,name3”格式? 完整代码 $str "name1,name2,name3"; $search "name2"; echo replaceString($str, $search);/** param $str&#xff0c;字符串格式:name1,name2…

C++:继承的介绍和深度解析

一、继承的概念和定义 1.什么是继承&#xff1f; 继承&#xff0c;顾名思义&#xff1a;就和现实生活中&#xff0c;孩子继承父母的东西有点类似。比如&#xff0c;你父亲的财产&#xff0c;你可以继承下来&#xff0c;你就可以使用父亲的钱。 官方一点的介绍&#xff1a; 继承…

JUC/多线程 模式(四)

一、同步模式之保护性暂停 即 Guarded Suspension &#xff0c;用在一个线程等待另一个线程的执行结果 产生结果的线程和使用结果的线程是一一对应的&#xff0c;有多少个生产结果的线程就有多少个使用结果的线程。 要点 有一个结果需要从一个线程传递到另一个线程&#xff0…

JUC/多线程原理(三)

一、Monitor 原理 二、synchronized 原理 (一)、基础 synchronized 即使内部抛出异常也会释放锁 (二)、轻量级锁 轻量级锁的使用场景&#xff1a;如果一个对象虽然有多线程要加锁&#xff0c;但加锁的时间是错开的&#xff08;也就是 没有竞争 &#xff09;&#xff0c;那么…

java分割回文串(力扣Leetcode131)

分割回文串 力扣原题链接 问题描述 给定一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是回文串。返回 s 所有可能的分割方案。 示例 示例 1: 输入&#xff1a;s “aab” 输出&#xff1a;[[“a”,“a”,“b”],[“aa”,“b”]] 示例 2: 输…

【御控物联】 IOT异构数据JSON转化(场景案例一)

文章目录 前言技术资料 前言 随着物联网、大数据、智能制造技术的不断发展&#xff0c;越来越多的企业正在进行工厂的智能化转型升级。转型升级第一步往往是设备的智能化改造&#xff0c;助力设备数据快速上云&#xff0c;实现设备数据共享和场景互联。然而&#xff0c;在生产…

爬虫逆向实战(38)-某空气质量平台(反调试,AES,DES,MD5)

一、数据接口分析 主页地址&#xff1a;某空气质量平台 1、抓包 (1) 反调试 该网站对鼠标右击以及F12进行了监听并拦截 虽然该网站无法打开Chrome控制台&#xff0c;导致我们无法抓包&#xff0c;但是道高一尺魔高一丈。既然我们无法在打开该网站的时候打开Chrome控制台&…

高架学习笔记之UML图概要

目录 零、什么是UML图 一、类图 二、对象图 三、构件图 四、部署图 五、制品图 六、包图 七、组合结构图 八、用例图 九、序列图 十、通信图 十一、状态图 十二、活动图 十三、定时图 十四、交互概览图 零、什么是UML图 统一建模语言&#xff08;Unified Modeli…

pytorch中的torch.hub.load():以vggish为例

pytorch提供了torch.hub.load()函数加载模型&#xff0c;该方法可以从网上直接下载模型或是从本地加载模型。官方文档 torch.hub.load(repo_or_dir, model, *args, sourcegithub, trust_repoNone, force_reloadFalse, verboseTrue, skip_validationFalse, **kwargs)参数说明&a…

【Qt】:坐标

坐标 一.常用快捷键二.使用帮助文档三.Qt坐标体系1.理论2.代码 一.常用快捷键 注释&#xff1a;ctrl / • 运⾏&#xff1a;ctrl R • 编译&#xff1a;ctrl B • 字体缩放&#xff1a;ctrl ⿏标滑轮 • 查找&#xff1a;ctrl F • 整⾏移动&#xff1a;ctrl shift ⬆/…

protobuf学习笔记(二):结合grpc生成客户端和服务端

上一篇文章大概讲了如何将自定义的protobuf类型的message转换成相应的go文件&#xff0c;这次就结合grpc写一个比较认真的客户端和服务器端例子 一、项目结构 client存放rpc服务的客户端文件 server存放rpc服务的服务端文件 protobuf存放自定义的proto文件 grpc存放生成的g…

代码随想录训练营Day36:● 435. 无重叠区间 ● 763.划分字母区间 ● 56. 合并区间

435. 无重叠区间 题目链接 https://leetcode.cn/problems/non-overlapping-intervals/description/ 题目描述 思路 直接统计重叠区间的个数&#xff0c;就是需要删除的个数 public int eraseOverlapIntervals(int[][] intervals) {Arrays.sort(intervals,(a,b)-> Intege…

【电子取证篇】哈希校验值的变与不变

【电子取证篇】哈希校验值的变与不变 哈希值&#xff08;散列值&#xff09;是针对电子数据内容来计算的&#xff0c;内容变则哈希变&#xff1b;但计算对象的文件名、文件时间等属性改变不会影响散列值&#xff01;&#xff01;&#xff01;—【蘇小沐】 &#xff08;一&…

点点数据K参数加密逆向分析(RPC方案跟加密算法还原)

文章目录 1. 写在前面2. 接口分析3. 断点分析4. RPC调用5. 算法还原 【&#x1f3e0;作者主页】&#xff1a;吴秋霖 【&#x1f4bc;作者介绍】&#xff1a;擅长爬虫与JS加密逆向分析&#xff01;Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长…

Nginx转发代理请求(http)+转发mysql(stream)

1.Nginx能处理的不同类型模块 1.1 http 模块 http 模块用于处理 HTTP 和 HTTPS 协议的请求和响应&#xff0c;通常用于构建 Web 服务器和反向代理服务器。通过 http 模块配置的服务可以处理 Web 浏览器发起的 HTTP 请求&#xff0c;并向客户端提供 Web 页面、静态资源、API 接…

linux通用命令 ssh命令连接慢问题排查

系列文章目录 文章目录 系列文章目录一、 ssh 连接慢3.1 查找原因3.2 解决方案 一、 ssh 连接慢 最近的 koji 服务器 使用 ssh 连接很慢。 3.1 查找原因 可以通过 ssh -vvv 192.168.0.123 或 time ssh root192.168.0.123 exit 查找原因如下&#xff1a; SERVER的SSHD会去DN…

【论文通读】UFO:A UI-Focused Agent for Windows OS Interaction

UFO&#xff1a;A UI-Focused Agent for Windows OS Interaction 前言AbstractMotivationMethodsExperimentConclusion 前言 Windows客户端第一个JARVIS&#xff0c;利用GPT4 Vision识别截图信息辅助智能体自动化执行操作&#xff0c;作为微软大肆宣传的一篇工作&#xff0c;其…

什么是齐纳二极管?齐纳二极管1SMB5944BT3G参数详解+应用方案

关于齐纳二极管基本知识&#xff1a; 齐纳二极管&#xff0c;又称稳压二极管。利用PN结的反向击穿状态&#xff0c;电流变化范围大&#xff0c;电压基本不变。制作了具有稳压功能的二极管。这种二极管是一个高电阻半导体器件&#xff0c;直到临界反向击穿电压。在这个临界击穿…

如何将Maven与TestNG集成

我们已经讨论了如何在maven中执行单元测试用例&#xff0c;但那些是JUnit测试用例&#xff0c;而不是TestNG。当maven使用“mvn test”命令进入测试阶段时&#xff0c;这些用例被执行。 本文将介绍如何将Maven与TestNG集成&#xff0c;并在maven进入测试阶段时执行TestNG测试。…

创新研报 | 2024+人工智能安全报告

人工智能(AI)是新一轮科技革命和产业变革的核心技术&#xff0c;被誉为下一个生产力前沿。具有巨大潜力的 AI 技术同时也带来两大主要挑战:一个是放大现有威胁&#xff0c;另一个是引入新型威胁。 奇安信预计&#xff0c;未来十年&#xff0c;人工智能技术的恶意使用将快速增长…