【最佳实践】配置类封装-Async异步注解以及自定义线程池

news2024/9/21 18:44:35

效果是:能点进去看到自定义的线程池,代表指定自定义的线程池成功!

image-20240411204924405

自定义Async线程池

自定义线程池

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;

/**
 * 线程池配置
 */
@Configuration
@Slf4j
public class ThreadPoolConfig {
    @Value("${asyncThreadPool.corePoolSize}")
    private int corePoolSize;

    @Value("${asyncThreadPool.maxPoolSize}")
    private int maxPoolSize;

    @Value("${asyncThreadPool.queueCapacity}")
    private int queueCapacity;

    @Value("${asyncThreadPool.keepAliveSeconds}")
    private int keepAliveSeconds;

    @Value("${asyncThreadPool.awaitTerminationSeconds}")
    private int awaitTerminationSeconds;

    @Value("${asyncThreadPool.threadNamePrefix}")
    private String threadNamePrefix;

    /**
     * 线程池配置
     * @return
     */
    @Bean(name = "threadPoolTaskExecutor")
    public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
        log.info("---------- 线程池开始加载 ----------");
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(corePoolSize);                        // 核心线程池大小
        threadPoolTaskExecutor.setMaxPoolSize(maxPoolSize);                          // 最大线程数
        threadPoolTaskExecutor.setQueueCapacity(keepAliveSeconds);                        // 队列容量
        threadPoolTaskExecutor.setKeepAliveSeconds(queueCapacity);                        // 活跃时间
        //threadPoolTaskExecutor.setAwaitTerminationSeconds(awaitTerminationSeconds);        // 主线程等待子线程执行时间
        threadPoolTaskExecutor.setThreadNamePrefix(threadNamePrefix);        // 线程名字前缀
        // RejectedExecutionHandler:当pool已经达到max-size的时候,如何处理新任务
        //      CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        threadPoolTaskExecutor.initialize(); // 初始化
        log.info("---------- 线程池加载完成 ----------");
        return threadPoolTaskExecutor;
    }
}

application.yml 配置

# @async 线程池配置
asyncThreadPool:
  corePoolSize: 10
  maxPoolSize: 50
  queueCapacity: 1000
  keepAliveSeconds: 60
  awaitTerminationSeconds: 600
  threadNamePrefix: asyncTask-

标准模板:优雅的写法

将配置文件(默认配置)与业务代码分离

MyAsyncThreadPoolExecutorProperties

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

@Data
@ConfigurationProperties(prefix = "async.thread.pool")
public class ThreadPoolTaskExecutorProperties {
    /**
     * 核心线程数
     */
    private int corePoolSize = 10;

    /**
     * 最大线程数
     */
    private int maxPoolSize = 50;

    /**
     * 队列容量
     */
    private int queueCapacity = 1000;

    /**
     * 线程存活时间
     */
    private int keepAliveSeconds = 60;

    /**
     * 等待终止时间
     */
    private int awaitTerminationSeconds = 600;

    /**
     * 线程名称前缀
     */
    private String threadNamePrefix = "asyncTask-";
}

MyAsyncThreadPoolExecutor

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
@EnableAsync
@EnableConfigurationProperties(ThreadPoolTaskExecutorProperties.class)
public class MyAsyncThreadPoolExecutor {

    private final ThreadPoolTaskExecutorProperties properties;

    @Autowired
    public MyAsyncThreadPoolExecutor(ThreadPoolTaskExecutorProperties properties) {
        this.properties = properties;
    }
    @Bean("threadPoolTaskExecutor")
    public ThreadPoolTaskExecutor threadPoolExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(properties.getCorePoolSize());
        threadPoolTaskExecutor.setMaxPoolSize(properties.getMaxPoolSize());
        threadPoolTaskExecutor.setQueueCapacity(properties.getQueueCapacity());
        threadPoolTaskExecutor.setKeepAliveSeconds(properties.getKeepAliveSeconds());
        threadPoolTaskExecutor.setAwaitTerminationSeconds(properties.getAwaitTerminationSeconds());
        threadPoolTaskExecutor.setThreadNamePrefix(properties.getThreadNamePrefix());
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }
}

测试使用

使用方法:可以指定或者不指定,最好指定!

    /**
     * @Async失效情况: TODO 异步发送方案OOM问题
     */
    @Async("threadPoolTaskExecutor")
    public void testSend(String site) {
        ///notify/v1/send-code?name=http://47.98.233.38:5212/login
        if (StrUtil.isBlank(site)) {
            site = "https://www.xdclass.net/";
        }

        // 发送验证码模拟
        ResponseEntity<String> forEntity = this.restTemplate.getForEntity(site, String.class);
        String body = forEntity.getBody();
        log.info(body);
    }

特征是:会显示用了哪个线程完成任务,但是不会呈现内部的worker执行细节(得看源码)

image-20240411210216507

注解失效问题

【官方】:如下方式会使@Async失效

一、异步方法使用static修饰
二、异步类没有使用@Component注解(或其他注解)导致spring无法扫描到异步类
三、异步方法不能与被调用的异步方法在同一个类中
四、类中需要使用@Autowired或@Resource等注解自动注入,不能自己手动new对象
五、如果使用SpringBoot框架必须在启动类中增加@EnableAsync注解

成功使用的原则是:

  1. 因为底层是由动态代理实现的,所以需要被spring管理
  2. 由spring管理,所以里面的类引用都是**@Autowired或@Resource等注解⾃动注⼊**,全程都要在spring的管辖范围内(方便使用动态代理的方式来完成异步调用),即调用者也必须是spring管理范围内的组件,不允许手动new对象
  3. 方法要求:public、非static非共享、返回值为void、Futrue

特点:

  • 底层还有一个线程池,要么自己实现,要么spring自带(超不推荐)
  • 动态代理实现

其他

简单demo写法

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
@EnableAsync
public class MyAsyncThreadPoolExecutor {
    @Bean("threadPoolTaskExecutor")
    public ThreadPoolTaskExecutor threadPoolExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(16);
        threadPoolTaskExecutor.setMaxPoolSize(64);
        threadPoolTaskExecutor.setQueueCapacity(1024);
        threadPoolTaskExecutor.setKeepAliveSeconds(60);
        threadPoolTaskExecutor.setAwaitTerminationSeconds(600);
        threadPoolTaskExecutor.setThreadNamePrefix("自定义线程池-");
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }
}

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

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

相关文章

Android14音频进阶之如何集成音效(八十五)

简介: CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布:《Android系统多媒体进阶实战》🚀 优质专栏: Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏: 多媒体系统工程师系列【原创干货持续更新中……】🚀 优质视频课程:AAOS车载系统+…

Parallels Desktop 20 版本功能汇总,附最新PD虚拟机下载链接

Parallels Desktop 20 for Mac 已正式发布&#xff01;作为目前 Mac 上极为好用强大的「虚拟机」软件&#xff0c;它完美支持最新的 macOS Sequoia 15 系统和 Windows 11 24H2&#xff0c;这次还引入了许多诸如 AI 等令人期待的全新功能和改进。为普通用户、开发者、设计师都带…

第十一章 【后端】商品分类管理微服务(11.2)——Lombok

11.2 Lombok 官网:https://projectlombok.org/ 较新版本的 idea 已默认安装 lombok 插件 Lombok 工具提供一系列的注解,使用这些注解可以不用定义 getter、setter、equals、constructor 等,可以消除 java 代码的臃肿,编译时它会在字节码文件中自动生成这些通用的方法,简…

【算法专题】穷举vs暴搜vs深搜vs回溯vs剪枝

二叉树剪枝 LCR 047. 二叉树剪枝 - 力扣&#xff08;LeetCode&#xff09; 本题要求我们将全部为0的二叉树去掉&#xff0c;也就是剪枝&#xff0c;当我们举一个具体的例子进行模拟时&#xff0c;会发现&#xff0c;只关注于对其中一个子树的根节点进行剪枝&#xff0c;由于我…

企业竞争文化数据,词频分析(2007-2022年)

企业竞争文化的核心价值观包括&#xff1a; 追求卓越&#xff1a;鼓励员工不断超越自我&#xff0c;提升个人和团队的绩效。领导力&#xff1a;强调领导者在塑造竞争文化中的重要作用&#xff0c;引领团队向更高目标前进。创新思维&#xff1a;倡导员工面对挑战时采取创新方法…

25届计算机专业选题推荐-基于微信小程序的校园快递驿站代收管理系统

&#x1f496;&#x1f525;作者主页&#xff1a;毕设木哥 精彩专栏推荐订阅&#xff1a;在 下方专栏&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; 实战项目 文章目录 实战项目 一、基于微信小程序的校园快递驿…

Golang | Leetcode Golang题解之第406题根据身高重建队列

题目&#xff1a; 题解&#xff1a; func reconstructQueue(people [][]int) (ans [][]int) {sort.Slice(people, func(i, j int) bool {a, b : people[i], people[j]return a[0] > b[0] || a[0] b[0] && a[1] < b[1]})for _, person : range people {idx : pe…

【SQL Server】清除日志文件ERRORLOG、tempdb.mdf

数据库再使用一段时间后&#xff0c;日志文件会增大&#xff0c;特别是在磁盘容量不足的情况下&#xff0c;更是需要缩减&#xff0c;以下为缩减方法&#xff1a; 如果可以停止 SQL Server 服务&#xff0c;那么可以采取更直接的方式来缩减 ERRORLOG 和 tempdb.mdf 文件的大小…

机器学习课程学习周报十二

机器学习课程学习周报十二 文章目录 机器学习课程学习周报十二摘要Abstract一、机器学习部分1.1 fGAN: General Framework of GAN1.2 CycleGAN1.3 Auto-Encoder1.4 概率论复习&#xff08;一&#xff09; 总结 摘要 本周的学习内容涵盖了fGAN框架、CycleGAN、自编码器以及概率…

【逐行注释】自适应Q和R的AUKF(自适应无迹卡尔曼滤波),附下载链接

文章目录 自适应Q的KF逐行注释的说明运行结果部分代码各模块解释 自适应Q的KF 自适应无迹卡尔曼滤波&#xff08;Adaptive Unscented Kalman Filter&#xff0c;AUKF&#xff09;是一种用于状态估计的滤波算法。它是基于无迹卡尔曼滤波&#xff08;Unscented Kalman Filter&am…

通义灵码在Visual Studio上

通义灵码在Visual Studio上不好用&#xff0c;有时候会出现重影&#xff0c;不如原生的自动补全好用&#xff0c;原生的毕竟的根据语法来给出提示的。

MySQL练手题--体育馆的人流量(困难)

一、准备工作 Create table If Not Exists Stadium (id int, visit_date DATE NULL, people int); Truncate table Stadium; insert into Stadium (id, visit_date, people) values (1, 2017-01-01, 10); insert into Stadium (id, visit_date, people) values (2, 2017-01-02…

Java 每日一刊(第8期):流程控制

“计算机程序本质上是艺术的一种表现形式。” 前言 这里是分享 Java 相关内容的专刊&#xff0c;每日一更。 本期将为大家带来以下内容&#xff1a; 条件控制语句循环控制语句跳转控制语句 条件控制语句 条件控制语句用于 根据条件判断执行不同的代码块&#xff0c;是编程…

COMP 6714-Info Retrieval and Web Search笔记week1

哭了哭了&#xff0c;这周唯一能听懂的就这门 目录 IR&#xff08;Information Retrieval)是什么&#xff1f;IR的基本假设Unstructured (text) vs. structuredDocuments vs. Database Records比较文本&#xff08;Comparing Text&#xff09;IR的范围(Dimensions of IR)IR的任…

【目标检测数据集】锯子数据集1107张VOC+YOLO格式

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;1107 标注数量(xml文件个数)&#xff1a;1107 标注数量(txt文件个数)&#xff1a;1107 标注…

如何使用myabtis log plugin插件展示出数据库查询语句

1、安装myabtis log plugin插件 直接插件市场搜该插件进行安装就行&#xff0c;安装完成后&#xff0c;会有如下图标 2、需要集成log4j springboot版本需要集成log4j&#xff0c;集成遇到的问题可以参考我之前文章 3、配置log4j.xml文件&#xff0c;添加mapper文件的打印 &l…

软考高级:存储系统 DAS、NAS、SAN 区别 - AI 解读

DAS&#xff08;直接附加存储&#xff09;、NAS&#xff08;网络附加存储&#xff09;和SAN&#xff08;存储区域网络&#xff09;是三种常见的数据存储架构&#xff0c;主要用于不同场景下的数据存储和管理。我们可以从它们的架构、用途以及优缺点来理解。 生活化例子 想象一…

标准库标头 <bit>(C++20)学习

<bit>头文件是数值库的一部分。定义用于访问、操作和处理各个位和位序列的函数。例如&#xff0c;有函数可以旋转位、查找连续集或已清除位的数量、查看某个数是否为 2 的整数幂、查找表示数字的最小位数等。 类型 endian (C20) 指示标量类型的端序 (枚举) 函数 bit_ca…

阿里云 Quick BI使用介绍

Quick BI使用介绍 文章目录 阿里云 Quick BI使用介绍1. 创建自己的quick bi服务器2. 新建数据源3. 上传文件和 使用4. 开始分析 -选仪表盘5. 提供的图表6. 一个图表的设置使用小结 阿里云 Quick BI使用介绍 Quick BI是一款全场景数据消费式的BI平台&#xff0c;秉承全场景消费…

文学智能体——摄影皮卡丘

前言 今天尝试进行智能体创建&#xff0c;我想创建什么呢&#xff0c;旅游的话&#xff0c;除了美食那就是摄影啦&#xff0c;那我就创建个皮卡丘吧&#xff0c;就决定是你啦&#xff0c;摄影皮卡丘&#xff01; 一、创建智能体 那怎么创建一个皮卡丘呢&#xff0c;那就使用…