Spring Boot注解@Async与线程池的配置

news/2024/11/19 14:40:07/

目录

使用异步注解创建异步任务

@Async注解

使用Demo

线程池配置

Spring Boot默认用于异步任务线程池配置

 线程池配置

 线程池隔离

为什么需要线程池隔离?

线程池隔离实现Demo

 线程池配置:

 异步任务:

测试demo

参考内容:


使用异步注解创建异步任务

@Async注解

异步注解,需要在 springboot主程序上配置@EnableAsync。

使用条件:任务本身之间不存在依赖关系

使用Demo

@Component
@Slf4j
public class AsyncTasksService {public static Random random = new Random();@Asyncpublic CompletableFuture<String> doTaskOne() throws Exception {log.info("doTaskOne()开始");long start = System.currentTimeMillis();Thread.sleep(random.nextInt(10000));long end = System.currentTimeMillis();log.info("doTaskOne()执行结束,耗时:" + (end - start) + "毫秒");return CompletableFuture.completedFuture("doTaskOne()执行结束");}@Asyncpublic CompletableFuture<String> doTaskTwo() throws Exception {log.info("doTaskTwo()开始");long start = System.currentTimeMillis();Thread.sleep(random.nextInt(10000));long end = System.currentTimeMillis();log.info("doTaskTwo()执行结束,耗时:" + (end - start) + "毫秒");return CompletableFuture.completedFuture("doTaskTwo()执行结束");}@Asyncpublic CompletableFuture<String> doTaskThree() throws Exception {log.info("doTaskThree()开始");long start = System.currentTimeMillis();Thread.sleep(random.nextInt(10000));long end = System.currentTimeMillis();log.info("doTaskThree()执行结束,耗时:" + (end - start) + "毫秒");return CompletableFuture.completedFuture("doTaskThree()执行结束");}
}
@SpringBootTest
@Slf4j
@RunWith(SpringRunner.class)
public class AsyncTasksTest {@Resourceprivate AsyncTasksService asyncTasksService;@Testpublic void test() throws Exception {long start = System.currentTimeMillis();CompletableFuture<String> task1 = asyncTasksService.doTaskOne();CompletableFuture<String> task2 = asyncTasksService.doTaskTwo();CompletableFuture<String> task3 = asyncTasksService.doTaskThree();CompletableFuture.allOf(task1, task2, task3).join();long end = System.currentTimeMillis();log.info("任务全部完成,总耗时:" + (end - start) + "毫秒");}
}

 测试结果:

11:02:20.078 [task-3] INFO  com.springwork.high.asyncTasks.AsyncTasksService - doTaskThree()开始
11:02:20.078 [task-1] INFO  com.springwork.high.asyncTasks.AsyncTasksService - doTaskOne()开始
11:02:20.078 [task-2] INFO  com.springwork.high.asyncTasks.AsyncTasksService - doTaskTwo()开始
11:02:24.453 [task-2] INFO  com.springwork.high.asyncTasks.AsyncTasksService - doTaskTwo()执行结束,耗时:4375毫秒
11:02:26.571 [task-1] INFO  com.springwork.high.asyncTasks.AsyncTasksService - doTaskOne()执行结束,耗时:6493毫秒
11:02:27.570 [task-3] INFO  com.springwork.high.asyncTasks.AsyncTasksService - doTaskThree()执行结束,耗时:7492毫秒
11:02:27.571 [main] INFO  com.springwork.high.AsyncTasksTest - 任务全部完成,总耗时:7500毫秒

线程池配置

为了控制异步任务的并发不影响到应用的正常运作,我们必须要对线程池做好相应的配置,防止资源的过渡使用

Spring Boot默认用于异步任务线程池配置

源码位置:org.springframework.boot.autoconfigure.task.TaskExecutionProperties

 线程池配置

spring:task:execution:pool:core-size: 8max-size: 5queue-capacity: 10keep-alive: 60sallow-core-thread-timeout: trueshutdown:await-termination: falseawait-termination-period:thread-name-prefix: hightask-
task:execution:pool:core-size: 8 (线程池创建时的初始化线程数,默认为8)max-size: 5 (线程池的最大线程数,默认为int最大值,即(2^31)-1)queue-capacity: 10 (用来缓冲执行任务的队列,默认为int最大值,即(2^31)-1)keep-alive: 60s  (线程终止前允许保持空闲的时间)allow-core-thread-timeout: true (是否允许核心线程超时)shutdown:await-termination: false (是否等待剩余任务完成后才关闭应用)await-termination-period: (等待剩余任务完成的最大时间)thread-name-prefix: hightask- (线程名的前缀)

 配置线程池,并将初始化线程数改成2后结果:

15:11:00.786 [hightask-1] INFO  com.springwork.high.asyncTasks.AsyncTasksService - doTaskOne()开始
15:11:00.786 [hightask-2] INFO  com.springwork.high.asyncTasks.AsyncTasksService - doTaskTwo()开始
15:11:02.434 [hightask-2] INFO  com.springwork.high.asyncTasks.AsyncTasksService - doTaskTwo()执行结束,耗时:1648毫秒
15:11:02.434 [hightask-2] INFO  com.springwork.high.asyncTasks.AsyncTasksService - doTaskThree()开始
15:11:04.397 [hightask-2] INFO  com.springwork.high.asyncTasks.AsyncTasksService - doTaskThree()执行结束,耗时:1963毫秒
15:11:04.757 [hightask-1] INFO  com.springwork.high.asyncTasks.AsyncTasksService - doTaskOne()执行结束,耗时:3971毫秒
15:11:04.757 [main] INFO  com.springwork.high.AsyncTasksTest - 任务全部完成,总耗时:3979毫秒

 线程池隔离

为什么需要线程池隔离?

@Async创建的异步任务都是共用的一个线程池,当有一些异步任务碰到性能问题的时候,是会直接影响其他异步任务的。

线程池隔离实现Demo

 线程池配置:

package com.springwork.high.asyncTasks;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;/*** @author gj* @version 1.0.0* @date 2023/5/26 15:25*/
@EnableAsync
@Configuration
public class AsyncTasksPoolConfig {@Bean(name = "highExecutor1")public Executor asyncTaskExecutor1() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(2);executor.setMaxPoolSize(2);executor.setQueueCapacity(10);executor.setKeepAliveSeconds(60);executor.setThreadNamePrefix("high-1-");executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());return executor;}@Bean(name = "highExecutor2")public Executor asyncTaskExecutor2() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(2);executor.setMaxPoolSize(2);executor.setQueueCapacity(10);executor.setKeepAliveSeconds(60);executor.setThreadNamePrefix("high-2-");executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());return executor;}
}

 异步任务:

package com.springwork.high.asyncTasks;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;import java.util.Random;
import java.util.concurrent.CompletableFuture;/*** @author gj* @version 1.0.0* @date 2023/5/26 10:17*/
@Component
@Slf4j
public class AsyncTasksService {public static Random random = new Random();@Async("highExecutor1")public CompletableFuture<String> doTaskOne(String taskName) throws Exception {log.info("开始任务:"+taskName);long start = System.currentTimeMillis();Thread.sleep(random.nextInt(10000));long end = System.currentTimeMillis();log.info("执行结束"+taskName+"耗时:" + (end - start) + "毫秒");return CompletableFuture.completedFuture("doTaskOne()执行结束");}@Async("highExecutor2")public CompletableFuture<String> doTaskTwo(String taskName) throws Exception {log.info("开始任务:"+taskName);long start = System.currentTimeMillis();Thread.sleep(random.nextInt(10000));long end = System.currentTimeMillis();log.info("执行结束"+taskName+"耗时:" + (end - start) + "毫秒");return CompletableFuture.completedFuture("执行结束");}
}

测试demo

        CompletableFuture<String> task1 = asyncTasksService.doTaskOne("1");CompletableFuture<String> task2 = asyncTasksService.doTaskOne("2");CompletableFuture<String> task3 = asyncTasksService.doTaskOne("3");CompletableFuture<String> task4 = asyncTasksService.doTaskTwo("4");CompletableFuture<String> task5 = asyncTasksService.doTaskTwo("5");CompletableFuture<String> task6 = asyncTasksService.doTaskTwo("6");CompletableFuture.allOf(task1, task2, task3,task4,task5,task6).join();

测试结果:

 15:44:50.899 [high-1-1] INFO  com.springwork.high.asyncTasks.AsyncTasksService - 开始任务:1
15:44:50.899 [high-2-2] INFO  com.springwork.high.asyncTasks.AsyncTasksService - 开始任务:5
15:44:50.899 [high-1-2] INFO  com.springwork.high.asyncTasks.AsyncTasksService - 开始任务:2
15:44:50.899 [high-2-1] INFO  com.springwork.high.asyncTasks.AsyncTasksService - 开始任务:4
15:44:51.159 [high-1-2] INFO  com.springwork.high.asyncTasks.AsyncTasksService - 执行结束2耗时:260毫秒
15:44:51.159 [high-1-2] INFO  com.springwork.high.asyncTasks.AsyncTasksService - 开始任务:3
15:44:51.442 [high-1-1] INFO  com.springwork.high.asyncTasks.AsyncTasksService - 执行结束1耗时:542毫秒
15:44:52.724 [high-1-2] INFO  com.springwork.high.asyncTasks.AsyncTasksService - 执行结束3耗时:1564毫秒
15:45:00.414 [high-2-2] INFO  com.springwork.high.asyncTasks.AsyncTasksService - 执行结束5耗时:9515毫秒
15:45:00.414 [high-2-2] INFO  com.springwork.high.asyncTasks.AsyncTasksService - 开始任务:6
15:45:00.690 [high-2-1] INFO  com.springwork.high.asyncTasks.AsyncTasksService - 执行结束4耗时:9791毫秒
15:45:00.764 [pool-2-thread-1] INFO  com.springwork.high.common.ScheduleTaskCommon - CurrentTime: 2023-05-26T15:45:00.764
15:45:08.855 [high-2-2] INFO  com.springwork.high.asyncTasks.AsyncTasksService - 执行结束6耗时:8440毫秒
15:45:08.856 [main] INFO  com.springwork.high.AsyncTasksTest - 任务全部完成,总耗时:17964毫秒

参考内容:

http://t.csdn.cn/Drzb4

http://t.csdn.cn/9usjv


http://www.ppmy.cn/news/89175.html

相关文章

mfc100.dll丢失如何解决?修复mfc100.dll的方法分享

mfc100.dll是Microsoft Visual C 2010中的一个动态链接库文件。如果该文件丢失&#xff0c;将会导致某些应用程序无法正常运行。在本文中&#xff0c;我们将探讨关于mfc100.dll丢失的问题&#xff0c;以及如何解决它。 一.什么是mfc100.dll mfc100.dll是Microsoft Visual C 20…

python 自动化学习(三) 句柄获取、模拟按键、opencv安装

一、什么是句柄 句柄是在操作系统中的一种标识符&#xff0c;相当于我们每个人的身份证一样&#xff0c;句柄在电脑中也是有唯一性的&#xff0c;我们启动的每一个程序都有自己的句柄号&#xff0c;表示自己的身份 为什么要说句柄&#xff0c;我们如果想做自动化操作时&#xf…

Bean的自动装配

目录结构 导入pom.xml依赖包 <dependencies><!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><vers…

《Cocos Creator游戏实战》老虎机抽奖效果实现思路

在线体验地址 Cocos Creator | SlotMachine Cocos Store 购买地址&#xff08;如果没有显示&#xff0c;那就是还在审核&#xff09;&#xff1a; https://store.cocos.com/app/detail/4958微店购买地址&#xff1a; https://weidian.com/item.html?itemID6338406353运行效果…

C#把类字段数据转成json数据存到本地txt文件,以及取出来

首先新建一个TxTModel类 public class TxTModel{public List<TXTData> Data { get; set; }//路径以及文件名string txtPath $"{Environment.CurrentDirectory}\\TxTData.txt"; public TxTModel(){//检查路径是否存在该文件&#xff0c;存在则取出来&#xff0…

图像处理:灰度图片线性截断拉伸

1. 为什么要拉伸 很多时候&#xff0c;灰度图片的灰度级较大&#xff0c;而像素值的分布比较集中&#xff0c;这就导致灰度级的利用率过低&#xff0c;从而导致图片的对比度很小&#xff0c;人眼的感官体验很不好&#xff0c;因此我们通常需要对原始的图像数据进行拉伸调整&…

助力工业物联网,工业大数据之一站制造业务主题划分【十三】

文章目录 01&#xff1a;一站制造业务主题划分02&#xff1a;一站制造业务维度设计03&#xff1a;一站制造业务主题维度矩阵 01&#xff1a;一站制造业务主题划分 目标&#xff1a;掌握一站制造的主题域及主题的划分实施 来源 主题域划分&#xff1a;业务或者部门划分 业务&am…

原地移除元素

原地移除元素 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用 O(1) 额外空间并原地修改输入数组。 暴力 class Solution { public:int remove…