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…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...
Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换
目录 关键点 技术实现1 技术实现2 摘要: 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式(自动驾驶、人工驾驶、远程驾驶、主动安全),并通过实时消息推送更新车…...

什么是VR全景技术
VR全景技术,全称为虚拟现实全景技术,是通过计算机图像模拟生成三维空间中的虚拟世界,使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验,结合图文、3D、音视频等多媒体元素…...
FTXUI::Dom 模块
DOM 模块定义了分层的 FTXUI::Element 树,可用于构建复杂的终端界面,支持响应终端尺寸变化。 namespace ftxui {...// 定义文档 定义布局盒子 Element document vbox({// 设置文本 设置加粗 设置文本颜色text("The window") | bold | color(…...