SpringBoot:自定义线程池配置类

news2024/11/24 20:39:23

文章目录

  • 一、前言
  • 二、案例展示
    • 1、初始版本
    • 2、代码审核意见和优化建议
    • 3、潜在问题和风险
    • 4、优化建议
    • 5、优化后的代码
  • 三、具体使用

在这里插入图片描述

一、前言

  • 有时候我们在项目中做一些长链路的跑批任务时,基于Springboot项目的定时任务,我们可以指定一个自定义的线程配置类进行单独提供给具体跑批任务使用,而不占用整个系统资源。

二、案例展示

  • 我们观察一下第一种方式和优化后的对比在哪里,关键点什么?

1、初始版本

@Configuration
@EnableAsync
public class ScheduledConfig {
   /**
     * 创建并配置一个线程池,用于快速执行任务。
     * 
     * @return Executor 返回一个配置好的线程池实例,可以用于快速执行任务。
     */
    @Bean("baseExecutor")
    public Executor fastExecutor() {
        // 创建 ThreadPoolTaskExecutor 实例
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 设置线程名前缀
        executor.setThreadNamePrefix("xxxx-schedule-baseExecutor");
        // 设置最大线程池大小
        executor.setMaxPoolSize(10);
        // 设置核心线程池大小
        executor.setCorePoolSize(8);
        // 设置队列容量
        executor.setQueueCapacity(5);
        // 设置拒绝执行处理器,采用CallerRunsPolicy策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }

2、代码审核意见和优化建议

3、潜在问题和风险

  • 异常处理: 线程池的默认异常处理机制可能不足以处理所有任务抛出的异常。尽管设置了CallerRunsPolicy作为拒绝执行处理器,它仅在线程池饱和时工作,并不直接处理任务执行中的异常。建议增强异常处理逻辑,例如通过自定义的RejectedExecutionHandler实现或者在任务代码中加入更细粒度的异常处理。
  • 资源泄露: 当应用停止时,如果线程池没有被正确关闭,可能会导致资源泄露。虽然Spring通常会管理Bean的生命周期,但最好确认ThreadPoolTaskExecutor的实例是否加入了适当的销毁逻辑,例如调用executor.shutdown()。
  • 线程数配置: CorePoolSize被设置为8,MaxPoolSize被设置为10,这意味着在高负载情况下,线程池只能扩展到10个线程。这样的配置可能不足以处理所有高峰时段的请求。你需要根据实际的负载测试结果调整这些参数。
  • 队列容量: 队列容量被固定为5。这意味着一旦队列满了,即使线程池还没有达到最大大小,任务也会被拒绝执行。根据实际的负载情况,考虑适当增加队列容量或调整线程池的大小。

4、优化建议

  • 性能监控: 考虑添加监控机制来跟踪线程池的性能指标,如活跃线程数、队列大小和拒绝执行的任务数等。这有助于及时发现和调整配置参数,以保证系统的稳定性。
  • 可调整性: 考虑将线程池的配置参数(如corePoolSize, maxPoolSize, queueCapacity等)设置为可从外部配置(例如应用配置文件)的方式获取。这样可以在不修改代码的情况下调整这些参数,以适应不同的运行环境。
  • 定制化: 如果有更复杂的需求,比如需要执行周期性任务或需要更细粒度的控制任务执行,可以考虑使用Spring提供的其他任务调度组件,如 ScheduledThreadPoolExecutor 或者集成 Quartz 等第三方库。

5、优化后的代码

@Configuration
@EnableAsync
public class ExecutorConfig {
	// 名字可以根据项目业务随意起
    @Bean("baseExecutor")
    public Executor fastExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        
        // 线程名前缀保持不变
        executor.setThreadNamePrefix("xxxx-schedule-base");
        
        // 调整核心线程池大小、最大线程池大小和队列容量,以适应可能的更高负载
        executor.setCorePoolSize(16); // 增加核心线程数
        executor.setMaxPoolSize(20); // 增加最大线程数
        executor.setQueueCapacity(100); // 增加队列容量
        
        // 使用自定义的RejectedExecutionHandler来处理任务被拒绝的情况
        executor.setRejectedExecutionHandler(new CustomRejectedExecutionHandler());
        
        // 确保在应用停止时线程池能被正确关闭
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            executor.shutdown();
        }));
        
        return executor;
    }

    // 自定义的拒绝执行处理器,以更好地处理任务被拒绝的情况
    static class CustomRejectedExecutionHandler implements RejectedExecutionHandler {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            // 这里可以加入更详细的日志记录或发送警报等逻辑
            System.out.println("Task " + r.toString() + " rejected from executor " + executor.toString());
        }
    }
}

三、具体使用

@Async("baseExecutor")
@Scheduled(cron = "0 0/5 * * * ?"){
// 具体业务
}

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

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

相关文章

C-偶遇行军蚁(遇到过的题,做个笔记)

我的代码: 思路就是把每一行看成一个字符串&#xff0c;然后逐渐增加字符就行 #include <iostream> #include <vector> using namespace std; int main() {string s;int n;cin >> n; //读入行数cin >> s; //读入字符串vector<string>arr(n…

一起来从Solidworks中导出URDF模型

这个博客是用来记录关于【从Solidworks中导出URDF模型】的学习历程&#xff1a; 相关课程链接见&#xff1a;如何从Solidworks导出URDF模型 • 古月 (guyuehome.com) 下面让我们一起开始吧&#xff01;&#xff01;&#xff01; 1. sw_urdf_exporter插件介绍 插件下载链接&…

共享社会经济路径(SSP1-5)中国及分省人口预估数据库_v2

v1数据集&#xff1a; 在共享社会经济路径&#xff08;SSPs&#xff09;全球框架下&#xff0c;根据本地化人口和经济参数&#xff0c;采用人口-发展-环境&#xff08;PDE&#xff09;模型&#xff0c;构建2020-2100年SSPs人口格点数据&#xff1b;采用柯布-道格拉斯&#xff…

基于STM32的汽车防窒息系统

文章目录 基于STM32的汽车防窒息系统系统简介材料展示视频制作硬件连接原理图PCB实物图GSM模块使用GSM模块代码 SGP30模块SGP30模块代码 步进电机驱动步进电机代码 其他模块主逻辑代码 总结 基于STM32的汽车防窒息系统 系统简介 随着社会的发展目前汽车的流行&#xff0c;汽车大…

vSAN vs SmartX 超融合:BI 数仓跑批效率对比测试

在《VMware 与 SmartX 分布式存储缓存机制浅析与性能对比》中&#xff0c;我们分析了 vSAN 7 缓存击穿的问题及其原因。近期&#xff0c;某金融用户在进行数据仓库分布式存储选型时&#xff0c;同样遭遇了测试过程中 vSAN 出现缓存击穿而难以完成全量跑批任务的问题。随后&…

安卓Android 架构模式及UI布局设计

文章目录 一、Android UI 简介1.1 在手机UI设计中&#xff0c;坚持的原则是什么1.2 安卓中的架构模式1.2.1 MVC (Model-View-Controller)设计模式优缺点 1.2.2 MVP(Model-View-Presenter)设计模式MVP与MVC关系&#xff1a; 1.2.3 MVVM(Model—View—ViewModel ) 设计模式1.2.4 …

ssm018简易版营业厅宽带系统+jsp

营业厅宽带系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本营业厅宽带系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间…

群晖NAS使用Docker部署大语言模型Llama 2结合内网穿透实现公网访问本地GPT聊天服务

文章目录 1. 拉取相关的Docker镜像2. 运行Ollama 镜像3. 运行Chatbot Ollama镜像4. 本地访问5. 群晖安装Cpolar6. 配置公网地址7. 公网访问8. 固定公网地址 随着ChatGPT 和open Sora 的热度剧增,大语言模型时代,开启了AI新篇章,大语言模型的应用非常广泛&#xff0c;包括聊天机…

新发现!科学家最新成果:补充类“原知因起源金”物质可延长寿命23%

近日&#xff0c;美哥伦比亚大学Vijay Yadav团队在《Science》发布了一项重磅级成果&#xff1a;通过补充一种特殊氨基酸&#xff08;带有磺酸基团的全能抗衰物质&#xff09;&#xff0c;竟然惊人地将实验动物的寿命延长了23%。 而其背后的机制&#xff0c;与早已火爆电商圈的…

Git命令(1)[删除,恢复与移动]

文章目录 1.删除文件1.1命令----rm <filename>1.2命令----git rm <filename>1.1命令----git rm <filename> -f 2.恢复文件2.1命令----git restore <filename>2.1命令----git restore --staged <filename> 3.重命名文件3.1命令----mv <oldFile…

javaweb学习(day10-服务器渲染技术)

一、基本介绍 1.前言 目前主流的技术是 前后端分离 (比如: Spring Boot Vue/React)JSP 技术使用在逐渐减少&#xff0c;但使用少和没有使用是两个意思&#xff0c;一些老项目和中小公司还在使用 JSP&#xff0c;工作期间&#xff0c;你很有可能遇到 JSPJSP 使用在减少(但是现…

分布式唯一ID 雪花算法

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;算法分析与设计 ⛺️稳中求进&#xff0c;晒太阳 算法具体介绍 雪花算法是 64 位 的二进制&#xff0c;一共包含了四部分&#xff1a; 1位是符号位&#xff0c;也就是最高位&#xff0c;…

基于Weibull、Beta、Normal分布的风、光、负荷场景生成及K-means场景削减方法

目录 一、主要内容&#xff1a; 二、代码运行效果&#xff1a; 三、Weibull分布与风机风速&#xff1a; 四、Beta分布与光伏辐照度&#xff1a; 五、Normal分布与电负荷&#xff1a; 六、K-means聚类算法&#xff1a; 七、完整代码数据下载&#xff1a; 一、主要内容&am…

vue3的动态组件

动态组件可以根据响应式变量动态的渲染不同的组件&#xff0c;目前是通过Vue 的 元素和特殊的 is attribute 实现的&#xff1a; <component :is"tabs[currentTab]"></component>:is 的值可以是以下几种&#xff1a; 被注册的组件名 导入的组件对象 你…

211基于matlab的多类结构动力学

基于matlab的多类结构动力学&#xff0c;凸轮机构、双凸轮、弦振动模拟、阻尼振动 、四连杆机构 、套杆运动 、三根弹簧作用的振子。程序已调通&#xff0c;可直接运行。 211 matlab 结构动力学 根弹簧作用的振子 - 小红书 (xiaohongshu.com)

蓝桥杯第793题——排水系统

题目描述 对于一个城市来说&#xff0c;排水系统是极其重要的一个部分。 有一天&#xff0c;小 C 拿到了某座城市排水系统的设计图。排水系统由 n 个排水结点&#xff08;它们从 1∼n 编号&#xff09;和若干个单向排水管道构成。每一个排水结点有若干个管道用于汇集其他排水…

SSM框架学习——工厂模式、Spring核心容器与Bean

工厂模式、核心容器与Spring Bean 工厂模式 工厂模式是Java中常用的一种设计模式&#xff0c;这种类型的设计模式属于创建型模式。说白了在代码层面就是取消了new的使用。 工厂模式有三种&#xff1a; 简单工厂模式工厂方法模式抽象工厂模式 举个例子&#xff0c;我们去买…

Ubuntu20.04安装MatlabR2018a

一、安装包 安装包下载链接 提取码&#xff1a;kve2 网上相关教程很多&#xff0c;此处仅作为安装软件记录&#xff0c;方便后续软件重装&#xff0c;大家按需取用。 二、安装 1. 相关文件一览 下载并解压文件后&#xff0c;如下图所示&#xff1a; 2. 挂载镜像并安装 2…

C++11---右值引用(深度讲解)

简要介绍 右值引用是C11的新特性,无论左值引用还是右值引用&#xff0c;都是在给对象取别名 什么是左值 什么是右值 1.左值,左值引用 左值是一个数据的表达式(例如变量或者解引用后的指针),我们可以对其进行取地址和修改赋值,左值可以出现在赋值符号的左边,而右值不能出现在…

深度解析C语言——预处理详解

对C语言有一定了解的同学&#xff0c;相信对预处理一定不会陌生。今天我们就来聊一聊一些预处理的相关知识。预处理是在编译之前对源文件进行简单加工的过程&#xff0c;主要是处理以#开头的命令&#xff0c;例如#include <stdio.h>、#define等。预处理是C语言的一个重要…