Springboot结合线程池的使用
1.使用配置文件配置线程的参数
配置文件
thread-pool:core-size: 100max-size: 100keep-alive-seconds: 60queue-capacity: 1
配置类
@Component
@ConfigurationProperties("thread-pool")
@Data
public class ThreadPoolConfig {private int coreSize;private int maxSize;private int keepAliveSeconds;private int queueCapacity;
}
2.配置线程池并使用
方式一:线程池结合CompletableFuture来实现
配置线程池类
@Configuration
public class ThreadPoolTask1 {@Autowiredprivate ThreadPoolConfig threadPoolConfig;@Bean("task1")public ThreadPoolTaskExecutor taskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(threadPoolConfig.getCoreSize()); // 核心线程数executor.setMaxPoolSize(threadPoolConfig.getMaxSize()); // 最大线程数executor.setKeepAliveSeconds(threadPoolConfig.getKeepAliveSeconds()); // 非核心线程活跃时间executor.setQueueCapacity(threadPoolConfig.getQueueCapacity()); // 队列容量executor.setThreadNamePrefix("test-"); // 设置线程的前缀名executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 设置拒绝策略executor.setWaitForTasksToCompleteOnShutdown(false); // 是否在任务执行完后关闭线程池executor.initialize();return executor;}
}
CompletableFuture使用线程池进行调用
package com.example.demo;import com.example.demo.config.ThreadPoolTask1;
import com.sun.java.browser.plugin2.DOM;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.stream.Collectors;@RestController
public class Demo {@Autowiredprivate DemoServiceImpl demoService;@Autowired@Qualifier("task1")private ThreadPoolTaskExecutor threadPoolTask1;@GetMapping("thread1")public Map<String, String> thread1() {long start = System.currentTimeMillis();List<CompletableFuture<String>> futures = new ArrayList<>();Map<String, String> map = new HashMap<>();// 使用CompletableFuture的 supplyAsync来处理结果相当于submit, runAsync无返回相当于executefor (int i = 0; i < 100; i++) {int b = i;CompletableFuture<String> future = CompletableFuture.supplyAsync(() ->demoService.executorTask1(b), threadPoolTask1);futures.add(future);}// 获取结果集CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()])).whenComplete((v, th) ->futures.stream().forEach(item -> {String result = null;try {result = item.get();} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}map.put(result.split("-")[1], result.split("-")[0]);})).join();long end = System.currentTimeMillis();map.put("当前时间",(end- start) + "");return map;}
}
任务类
public String executorTask1(int i) {System.out.println("当前线程-" + Thread.currentThread().getName());try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}if (i == 6) {throw new RuntimeException("cs");} else {return "aaa-" + i;}}
方式二:使用@EnableAsync和@Async方式实现
在启动类上加@EnableAsync注解
// 加上@EnableAsync注解,也可以在自己的配置类上加
@EnableAsync // 开启对异步任务的支持
@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}
}
编写线程池配置
// 也可以在此处加上@EnableAsync注解,入口类上不加
@Configuration
public class ThradPoolTask{@Autowiredprivate ThreadPoolConfig threadPoolConfig;@Beanpublic Executor taskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(threadPoolConfig.getCoreSize()); // 核心线程数executor.setMaxPoolSize(threadPoolConfig.getMaxSize()); // 最大线程数executor.setKeepAliveSeconds(threadPoolConfig.getKeepAliveSeconds()); // 非核心线程活跃时间executor.setQueueCapacity(threadPoolConfig.getQueueCapacity()); // 队列容量executor.setThreadNamePrefix("test-"); // 设置线程的前缀名executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 设置拒绝策略executor.setWaitForTasksToCompleteOnShutdown(false); // 是否在任务执行完后关闭线程池executor.initialize();return executor;}
}
使用
@RestController
public class Demo {@Autowiredprivate DemoServiceImpl demoService;@GetMapping("thread")public Map<String, String> thread() {long start = System.currentTimeMillis();Map<String, String> map = new HashMap<>();List<Future<String>> futures = new ArrayList<>();for (int i = 0; i < 100; i++) {Future<String> future = demoService.executorTask(i);futures.add(future);}int b = 1;futures.forEach(item -> {try {String result = item.get();map.put(result.split("-")[1], result.split("-")[0]);} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}});long end = System.currentTimeMillis();map.put("当前时间",(end- start) + "");return map;}
}
任务类
// 必须指明使用的是哪个线程池,taskExecutor不带的话用springboot默认注册的线程池// Future作为返回值,携带返回结果@Async("taskExecutor")public Future<String> executorTask(int i) {System.out.println("当前线程-" + Thread.currentThread().getName());try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}if (i == 6) {throw new RuntimeException("cs");} else {// AsyncResult返回携带的结果return new AsyncResult<String>("aaa-" + i);}}
方式三:重写springboot默认的线程池配置
在启动类上加@EnableAsync注解
// 加上@EnableAsync注解,也可以在自己的配置类上加
@EnableAsync
@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}
}
@Configuration
public class ThreadPoolTask2 implements AsyncConfigurer {@Autowiredprivate ThreadPoolConfig threadPoolConfig;/*** 修改默认线程池的配置** @return*/@Overridepublic Executor getAsyncExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(threadPoolConfig.getCoreSize()); // 核心线程数executor.setMaxPoolSize(threadPoolConfig.getMaxSize()); // 最大线程数executor.setKeepAliveSeconds(threadPoolConfig.getKeepAliveSeconds()); // 非核心线程活跃时间executor.setQueueCapacity(threadPoolConfig.getQueueCapacity()); // 队列容量executor.setThreadNamePrefix("test2-"); // 设置线程的前缀名executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 设置拒绝策略executor.setWaitForTasksToCompleteOnShutdown(false); // 是否在任务执行完后关闭线程池executor.initialize();return executor;}/*** 修改默认的异常处理* 注意:如果带有返回值Future,异常会被捕获,不会去执行该方法** @return*/@Overridepublic AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {return (ex, method, params) -> {System.out.println("任务执行的异常" + ex);System.out.println("执行的任务方法" + method.getName());for (Object param : params) {System.out.println("执执行任务的参数" + param);}};}
}
使用
@RestController
public class Demo {@Autowiredprivate DemoServiceImpl demoService;// 不带返回值的任务@GetMapping("thread2")public Map<String, String> thread2() {long start = System.currentTimeMillis();Map<String, String> map = new HashMap<>();List<Future<String>> futures = new ArrayList<>();for (int i = 0; i < 100; i++) {demoService.executorTask2(i);}return null;}// 带有返回值的任务@GetMapping("thread3")public Map<String, String> thread3() {long start = System.currentTimeMillis();Map<String, String> map = new HashMap<>();List<Future<String>> futures = new ArrayList<>();for (int i = 0; i < 100; i++) {Future<String> future = demoService.executorTask3(i);futures.add(future);}int b = 1;futures.forEach(item -> {String result = null;try {result = item.get();} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}map.put(result.split("-")[1], result.split("-")[0]);});long end = System.currentTimeMillis();map.put("当前时间",(end- start) + "");return map;}
}
任务类
// @Async不需要指定,使用默认即可// 出现异常会走AsyncUncaughtExceptionHandler方法@Asyncpublic void executorTask2(int i) {System.out.println("当前线程-" + Thread.currentThread().getName());try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}int a = 1/0;}// 即使出现异常也不会走AsyncUncaughtExceptionHandler方法@Asyncpublic Future<String> executorTask3(int i) {System.out.println("当前线程-" + Thread.currentThread().getName());try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}if (i == 6) {throw new RuntimeException("cs");} else {return new AsyncResult<String>("aaa-" + i);}}
关于三种在执行过程中的异常
方式一:导致请求失败:最好在任务中进行处理
方式二:请求成功了,关于6的那条数据并没有返回给前端
方式三:请求成功了,关于6的那条数据并没有返回给前端
相关文章:

Springboot结合线程池的使用
1.使用配置文件配置线程的参数 配置文件 thread-pool:core-size: 100max-size: 100keep-alive-seconds: 60queue-capacity: 1配置类 Component ConfigurationProperties("thread-pool") Data public class ThreadPoolConfig {private int coreSize;private int ma…...

AOP工作流程
AOP工作流程3,AOP工作流程3.1 AOP工作流程流程1:Spring容器启动流程2:读取所有切面配置中的切入点流程3:初始化bean流程4:获取bean执行方法验证容器中是否为代理对象验证思路步骤1:修改App类,获取类的类型步骤2:修改MyAdvice类,不增强步骤3:运行程序步骤…...

Modbus相关知识点及问题总结
本人水平有限,写得不对的地方望指正 困惑:线圈状态的值是否是存储在线圈寄存器里面?是否有线圈寄存器的说法?网上有说法说是寄存器占两个字节,但线圈的最少操作单位是位。类似于继电器的通断状态,直接根据电…...

【MySQL】函数
文章目录1. DQL执行顺序2. 函数2.1 字符串函数2.2 数值函数2.3 日期函数2.4 流程函数2.5 窗口函数2.5.1 介绍2.5.2 聚合窗口函数2.5.3 排名窗口函数2.5.4 取值窗口函数1. DQL执行顺序 2. 函数 2.1 字符串函数 函数功能concat(s1,s2,…sn)字符串拼接,将s1,s2…sn拼…...

MySQL高级
一、基础环境搭建 环境准备:CentOS7.6(系统内核要求是3.10以上的)、FinalShell 1. 安装Docker 帮助文档 : https://docs.docker.com/ 1、查看系统内核(系统内核要求是3.10以上的) uname -r2、如果之前安装过旧版本的D…...

带你弄明白c++的4种类型转换
目录 C语言中的类型转换 C强制类型转换 static_cast reinterpret_cast const_cast dynamic_cast RTTI 常见面试题 这篇博客主要是帮助大家了解和学会使用C中规定的四种类型转换。首先我们先回顾一下C语言中的类型转换。 C语言中的类型转换 在C语言中,如果赋…...

8个明显可以提升数据处理效率的 Python 神库
在进行数据科学时,可能会浪费大量时间编码并等待计算机运行某些东西。所以我选择了一些 Python 库,可以帮助你节省宝贵的时间 文章目录1、Optuna技术提升2、ITMO\_FS3、Shap-hypetune4、PyCaret5、floWeaver6、Gradio7、Terality8、Torch-Handle1、Optun…...

互联网公司吐槽养不起程序员,IT岗位的工资真是虚高有泡沫了?
说实话,看到这个话题的时候又被震惊到。 因为相比以往,程序员工资近年来已经够被压缩的了好嘛? 那些鼓吹泡沫论的,真就“何不食肉糜”了~~~ 而且这种逻辑就很奇怪, 程序员的薪资难道不是由行业水平决定么ÿ…...

Excel 进阶|只会 Excel 也能轻松搭建指标应用啦
现在,Kyligence Zen 用户可在 Excel 中对指标进行更进一步的探索和分析,能够实现对维度进行标签筛选、对维度基于指标值进行筛选和排序、下钻/上卷、多样化的透视表布局、本地 Excel 和云端 Excel 的双向支持等。业务人员和分析师基于现有分析习惯就可以…...

RabbitMQ中TTL
目录一、TTL1.控制后台演示消息过期2.代码实现2.1 队列统一过期2.2 消息过期一、TTL TTL 全称 Time To Live(存活时间/过期时间)。 当消息到达存活时间后,还没有被消费,会被自动清除。 RabbitMQ可以对消息设置过期时间࿰…...

Ceres简介及示例(4)Curve Fitting(曲线拟合)
文章目录1、Curve Fitting1.1、残差定义1.2、 Problem问题构造1.3、完整代码1.4、运行结果2、Robust Curve Fitting1、Curve Fitting 到目前为止,我们看到的示例都是没有数据的简单优化问题。最小二乘和非线性最小二乘分析的原始目的是对数据进行曲线拟合。 以一个…...

音质最好的骨传导蓝牙耳机有哪些,推荐几款不错的骨传导耳机
骨传导耳机也称为“不入耳式”耳机,是一种通过颅骨、骨迷路、内耳淋巴液和听神经之间的信号传导,来达到听力保护目的的一种技术。由于它可以开放双耳,所以在跑步、骑行等运动时使用十分安全,可以避免外界的干扰。这种耳机在佩戴…...
计算机操作系统安全
操作系统安全是计算机系统安全的重要组成部分,目的是保护操作系统的机密性、完整性和可用性。在当前的网络环境下,操作系统面临着许多威胁,如病毒、木马、蠕虫、黑客攻击等等。为了保护操作系统的安全,需要采取各种措施来防范这些…...

超详细从入门到精通,pytest自动化测试框架实战教程-用例标记/执行(三)
目录:导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜)前言 pytest可以通过标记…...

Java SE 基础(5) Java 环境的搭建
Java 虚拟机——JVM JVM (Java Virtual Machine ):Java虚拟机,简称JVM,是运行所有Java程序的假想计算机,是Java程序的运行环境,是Java 最具吸引力的特性之一。我们编写的Java代码,都…...

银行数字化转型导师坚鹏:银行对公客户数字化场景营销案例萃取
银行对公客户数字化场景营销案例萃取与行动落地课程背景: 很多银行存在以下问题:不清楚银行数字化营销与场景营销内涵?不知道如何开展对公客户数字化营销工作?不知道对公业务数字化场景营销成功案例? 学员收获&a…...
get和post的区别
1.用途上 get请求用来向服务器获取资源; post请求用来向服务器提交数据; 2.表单提交方式上 get请求直接将表单数据拼接到URL上,多个参数之间通过&符号连接; post请求将表单数据放到请求头或者请求体中; 3.传…...
Java调用Oracle存储过程
文章目录 Java调用Oracle存储过程Java调用Oracle存储过程 使用Java实现存储过程的步骤: 1、数据表、存储过程【已完成】 2、引入依赖包、数据源配置 3、Java实现【已完成】 – Oracle 创建数据表 CREATE TABLE STUDENT ( ID NUMBER (20) NOT NULL ENABLE PRIMARY KEY, NAME V…...
ubuntu如何设置qt环境变量
Qt 是一个1991年由Qt Company开发的跨平台C图形用户界面应用程序开发框架。它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器。Qt是面向对象的框架,使用特殊的代码生成扩展(称为元对象编译器(Meta Object Compi…...

高管对谈|揭秘 NFT 技术背后的研发方法论
有人说,元宇宙是未来,NFT 则是通往这个可能的未来的数字通行证。 经过一度热炒之后,NFT 逐渐回归理性的「大浪淘沙」轨迹。NXTF_(廿四未来)正是一家将 NFT 向实体经济靠拢并与之结合的公司。 NXTF_利用区块链技术&am…...

深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...

【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...