线程池技术实现及参数工作流程原理

news2024/11/26 4:21:21

一.什么是线程池

        线程池其实就是一种多线程处理形式,处理过程中可以将任务添加到队列中,然后在创建线程后自动启动这些任务。这里的线程就是我们前面学过的线程,这里的任务就是我们前面学过的实现了Runnable或Callable接口的实例对象。

为什么使用多线程

1.线程管理复杂 何时创建线程,何时销毁线程

2.任务管理复杂 任务什么时候接收,任务什么时候拒绝

二.线程池的实现及原理

  • Spring 中可以用 ThreadPoolTaskExecutor 配合 @Async 注解来实现(不太推荐)
  • Java 中,可以使用 JUC 并发包中的 ThreadPoolExecutor 来实现非常灵活的自定义线程池(推荐)。
线程池参数
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
  • corePoolSize(核心线程数 => 正式员工数量):正常情况下,我们系统应该能同时工作的线程数
  • maximumPoolSize(最大线程数 =>最多招多少人):极限情况下,我们线程池最多有多少个线程。
  • keepAliveTime(空闲线程存活时间):非核心线程在没有任务的情况下,过多久删除掉(理解为开除临时工)
  • TimeUnit unit(空闲线程存活时间的单位):分钟、秒
  • workQueue(工作队列):用于存放给线程执行的任务,存在队列的最大长度(一定要设置队列长度,不要设置成无限大)。
  • threadFactory(线程工厂):控制每个线程的生成、线程的属性(比如线程名)
  • RejectedExecutionHandler(拒绝策略):任务队列满的时候,我们采取什么策略,比如抛异常、不抛异常,自定义策略。
工作流程图

线程池工作机制
  1. 核心线程
    • 初始时,线程池有corePoolSize个核心线程(例如2个)。
    • 当提交新任务时,如果核心线程数未满,则直接由核心线程处理。
  2. 任务队列
    • 当核心线程都在忙碌时,新任务会被放入workQueue(阻塞队列)中等待处理。
    • workQueue的大小限制了能够等待的任务数量。
  3. 最大线程数
    • 如果workQueue已满,且当前线程数小于maximumPoolSize(例如4个),则线程池会创建新的临时线程来处理任务。
  4. 拒绝策略
    • workQueue已满,且线程数已达到maximumPoolSize时,再提交新任务会触发RejectedExecutionHandler定义的拒绝策略(如抛异常、丢弃任务等)。
  5. 空闲线程超时
    • 当线程池中的线程数量超过corePoolSize时,如果某个线程在keepAliveTime时间段内没有执行任务,那么该线程会被终止,以减少资源消耗。
举例有9个任务的情况

核心线程数为2  最大线程数为4  任务队列长度为4

核心线程是正式工,非核心线程是临时工
 

加入任务1,2    分配给核心线程1,2

加入任务3,此时核心线程数已满,看任务队列是否空闲,加入队列

陆续加入4,5,6到队列中

此时队列已满,任务7需要创建线程a,处理

任务8创建线程b处理

当有任务9时,此时最大线程数已满,无法创建线程,拒绝执行

如何确定线程池参数?

根据实际情况(实际业务场景 和 系统资源)来调整测试,不断优化参数。

比如:现有条件 AI 并发只允许 4 个任务同时执行,允许 20 个任务排队。

以上需求可设置如下参数:

  • corePoolSize(核心线程数):正常情况设置为 4
  • maximumPoolSize(最大线程数):设置为极限情况,数量 >= 4
  • keepAliveTime(空闲线程存活时间):一般设置为秒级/分钟级
  • TimeUnit unit(空闲线程存活时间的单位):分钟、秒
  • workQueue(工作队列):结合实际情况,可以设置为 20( AI 允许 20 个任务排队)
  • RejectedExecutionHandler(拒绝策略):抛异常,标记数据库任务状态为 “任务满了,已拒绝”
任务的划分(I/O 或计算密集型)

CPU (计算)密集型:计算较多,比如音视频处理、图像处理、数学计算等,一般设置 corePoolSize 为 CPU 的核心数 + 1 ( N+1 )。

I/O 密集型:吃带宽/内存/硬盘的读写资源,corePoolSize 可以设置大一点,通常经验值为 2N(N 为核心数),但建议以 I/O 能力为主。

优点:合理设置核心数能够让线程最大化利用 CPU,不至于频繁切换线程。

三.线程池示例代码

@Configuration
//创建线程池配置类
public class ThreadPoolExecutorConfig {
    @Bean //方法返回值对象加入容器里面
    public ThreadPoolExecutor generate(){
        //新建一个线程工厂
        ThreadFactory threadFactory=new ThreadFactory() {
            int count=1;//初始线程数
            @Override//重写线程创建方法
            //@NotNull保证参数r不为空
            public Thread newThread(@NotNull Runnable r) {
                Thread thread = new Thread(r);
                thread.setName("线程"+count);//设置线程名字为线程数
                count++;
                return thread;//返回线程
            }
        };//创建一个线程池对象 指定各个参数//任务队列是阻塞队列//自定义线程工厂创建线程
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 4, 100, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(4), threadFactory);
    return threadPoolExecutor;//返回线程池对象
    }
}
@Slf4j
@RestController
@Controller
@RequestMapping("/queue")
public class QueueController {
    @Autowired
    ThreadPoolExecutor threadPoolExecutor;
    @GetMapping("/add")
        public void add(String name){
        //CompletableFuture.runAsync()方法是用来异步地执行一个无返回值的Runnable任务
        CompletableFuture.runAsync(()->{
            log.info("任务执行中"+name+"执行者"+Thread.currentThread().getName());
            try {
                Thread.sleep(600000);//模拟长时间占用
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //异步任务在threadPoolExecutor里面执行
        },threadPoolExecutor);
        }

        @PostMapping("/get")
    public String get(){
            HashMap<String, Object> map = new HashMap<>();
            //获取任务总数
            long tasktotal=threadPoolExecutor.getTaskCount();
            //获取已经完成任务数
            long completedTaskCount = threadPoolExecutor.getCompletedTaskCount();
            //获取存活时间
            int activeCount = threadPoolExecutor.getActiveCount();
            //获取核心线程数
            int corePoolSize = threadPoolExecutor.getCorePoolSize();
            //获取最大线程数
            int maximumPoolSize = threadPoolExecutor.getMaximumPoolSize();
            //获取队列长度
            int size = threadPoolExecutor.getQueue().size();
            map.put("任务总数",tasktotal);
            map.put("已经完成任务数",completedTaskCount);
            map.put("存活时间",activeCount);
            map.put("核心线程数",corePoolSize);
            map.put("最大线程数",maximumPoolSize);
            map.put("队列长度",size);
            return JSONUtil.toJsonStr(map);

        }

}

 

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

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

相关文章

【RT摩拳擦掌】RT云端测试之百度天工物接入构建(设备型)

【RT摩拳擦掌】RT云端测试之百度天工物接入构建&#xff08;设备型&#xff09; 一&#xff0c; 文档介绍二&#xff0c; 物接入IOT Hub物影子构建2.1 创建设备型项目2.2 创建物模型2.3 创建物影子 三&#xff0c; MQTT fx客户端连接云端3.1 MQTT fx配置3.2 MQTT fx订阅3.3 MQT…

修改docker中mongodb容器的时区

假设容器名称为mongodb&#xff0c;设置时区为上海时区的命令为&#xff1a; docker exec -it mongodb bash -c "ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo Asia/Shanghai > /etc/timezone"验证时区更改&#xff1a; docker e…

Eigen中关于四元数的常用操作

四元数&#xff08;Quaternion&#xff09;是一种数学工具&#xff0c;广泛用于计算机图形学、机器人学和物理模拟中&#xff0c;特别适合处理三维旋转。Eigen库是一个高性能的C数学库&#xff0c;提供了丰富的线性代数功能&#xff0c;其中就包括对四元数的支持。 1. 为什么选…

element ui form 表单验证

表单验证方法 在el-form元素上总体设置校验规则rules&#xff0c;下面是官方案例 <el-form :model"ruleForm" :rules"rules" ref"ruleForm" label-width"100px" class"demo-ruleForm"><el-form-item label"…

基于Java游戏售卖网站详细设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;…

从零开始学Spring Boot系列-集成Spring Security实现用户认证与授权

在Web应用程序中&#xff0c;安全性是一个至关重要的方面。Spring Security是Spring框架的一个子项目&#xff0c;用于提供安全访问控制的功能。通过集成Spring Security&#xff0c;我们可以轻松实现用户认证、授权、加密、会话管理等安全功能。本篇文章将指导大家从零开始&am…

Qt Creator创建一个用户登录界面

目录 1 界面设计 2 代码 2.1 登录界面 2.2 注册界面 2.3 登陆后的界面 3 完整资源 这里主要记录了如何使用Qt Creator创建一个用户登录界面&#xff0c;能够实现用户的注册和登录功能&#xff0c;注册的用户信息存储在了一个文件之中&#xff0c;在登录时可以比对登录信息…

模型预测控制:线性MPC

模型预测控制&#xff1a;线性MPC 模型预测控制&#xff08;Model Predictive Control, MPC&#xff09;是一种广泛应用于工业过程控制和自动驾驶等领域的先进控制技术。MPC通过在线解决优化问题来计算控制输入&#xff0c;从而实现系统的最优控制。本文将介绍线性MPC的系统模…

C# 实现websocket双向通信

&#x1f388;个人主页&#xff1a;靓仔很忙i &#x1f4bb;B 站主页&#xff1a;&#x1f449;B站&#x1f448; &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;C# &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff…

【地理库 Turf.js】

非常全面的地理库 &#xff0c; 这里枚举一些比较常用&#xff0c;重点的功能&#xff0c; 重点功能 提供地理相关的类&#xff1a;包括点&#xff0c;线&#xff0c;面等类。 测量功能&#xff1a;点到线段的距离&#xff0c;点和线的关系等。 判断功能&#xff1a; 点是否在…

Ubuntu系统打包ISO镜像文件

本文以ubuntu20.04系统为例 1.Systemback简介 Systemback 是一个开源的系统备份和恢复工具&#xff0c;它主要用于 Linux 操作系统。Systemback 可以帮助用户创建完整的系统备份&#xff0c;包括操作系统、应用程序、用户数据等&#xff0c;并且可以在需要时将系统恢复到备份的…

5G频段简介

5G频段 5G网络一共有29个频段&#xff0c;主要被分为两个频谱范围&#xff0c;其中6GHz以下的频段共有26个&#xff08;统称为Sub6GHz&#xff09;&#xff0c;毫米波频段有3个。目前国内主要使用的是Sub6GHz&#xff0c;包括n1/n3/n28/n41/n77/n78/n79共7个频段。具体介绍如下…

centos上部署Ollama平台,实现语言大模型本地部署

网上有很多大模型&#xff0c;很多都是远程在线调用ChatGPT的api来实现的&#xff0c;自己本地是没有大模型的&#xff0c;这里和大家分享一个大模型平台&#xff0c;可以实现本地快速部署大模型。 Ollama是一个开源项目&#xff0c;它提供了一个平台和工具集&#xff0c;用于部…

SerDes介绍以及原语使用介绍(2)OSERDESE2原语仿真

文章目录 前言一、SDR模式1.1、设计代码1.2、testbench代码1.3、仿真分析 二、DDR模式下2.1、设计代码2.2、testbench代码2.3、仿真分析 三、OSERDES2级联3.1、设计代码3.2、testbench代码3.3、代码分析 前言 上文通过xilinx ug471手册对OSERDESE有了简单的了解&#xff0c;接…

数字化那点事:一文读懂数字乡村

一、数字乡村的定义 数字乡村是指利用信息技术和数字化手段&#xff0c;推动乡村社会经济发展和治理模式变革&#xff0c;提升乡村治理能力和公共服务水平&#xff0c;实现乡村全面振兴的一种新型发展模式。它包括农业生产的数字化、乡村治理的智能化、乡村生活的现代化等方面…

智慧校园-医务管理系统总体概述

智慧校园医务管理系统&#xff0c;作为校园健康管理体系的智能化升级&#xff0c;深度融合信息技术与医疗服务&#xff0c;为师生构筑起一道全方位的健康守护网。医务管理系统以提升校园医疗服务水平、优化健康管理流程为核心目标&#xff0c;通过一系列创新功能&#xff0c;确…

29.9一份的烤鸭,抖音为什么卖不出去?

文 | 螳螂观察 作者 | 青月 这两年&#xff0c;我的抖音推荐里&#xff0c;越来越常出现附近几km内的美食推荐。 就在昨天晚上&#xff0c;当我惯常打开抖音&#xff0c;才刷了几个视频&#xff0c;就跳出了一家距离我只有1.6km的烤鸭店。 这个短视频中&#xff0c;烤鸭在滋…

Python数据分析案例47——笔记本电脑价格影响因素分析

案例背景 博主对电脑的价格和配置一直略有研究&#xff0c;正好最近也有笔记本电脑相关的数据&#xff0c;想着来做点分析吧&#xff0c;写成一个案例。基本上描述性统计&#xff0c;画图&#xff0c;分组聚合&#xff0c;机器学习&#xff0c;交叉验证&#xff0c;搜索超参数…

基于语音识别的智能电子病历(二)苹果端的语音接入

是2011年参与的&#xff0c;俺负责Wav文件处理、FTP通讯和一些后端部分。iPhone/iPad/iPod Recorder 前2年还在APP Store上 说明 Step-by-Step Procedure to Install App and Use the FnetRecorder Download the App from Apple Store Launch Apple Store and key in “fnetr…

SpringBoot学习05-[SpringBoot的嵌入式Servlet容器]

SpringBoot的嵌入式Servlet容器 嵌入式Servlet容器servlet容器-嵌入式servlet容器配置修改通过全局配置文件修改修改添加实现了WebServerFactoryCustomizer接口的bean来进行修改 servlet容器-注册servlet三大组件 嵌入式Servlet容器 SpringBoot包含对嵌入式Tomcat、Jetty、Und…