目录
使用异步注解创建异步任务
@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