SpringBoot使用多线程
一 概述
1 为什么使用多线程
在我们开发系统过程中,经常会处理一些好费时间的任务(如向数据库中插入上百万数据,将会导致系统阻塞),这个时候就会自然想到使用多线程。
当数据量大的时候,一个新的线程满足不了系统的要求,但是只有少量的请求可以直接new一个新线程,如下代码。
// 少量请求可以这样做
new Thread(){
@Override
public void run() {
//TODO异步任务
}
}.start();
2 为什么使用Spring来实现多线程
- 使用Spring比使用JDK原生的并发API更简单。(
@Async
就能解决)。 - 一般的开发环境都会集成Spring框架,Bean也都交给Spring来管理,因此,Spring实现多线程更简单。
3 为什么需要使用异步(多线程)
传统的调用方式:调用一个服务,需要等待服务调用完成后,才能执行后面的代码,因此,需要等待时间。
使用异步的方式:调用一个服务的同时,继续执行后面的代码,几乎是不需要多少的等待时间。
二 SpringBoot使用多线程
1 如何使用
在 SpringBoot 中对其进行了简化处理,只需要配置一个类型为 java.util.concurrent.TaskExecutor
或其子类( 一般使用 Spring 提供的ThreadPoolTaskExecutor 类)的Bean,并在配置类或直接在程序入口类上声明注解 @EnableAsync。
调用也简单,在由Spring管理的对象的方法上标注注解 @Async,显式调用即可生效。
2 配置多线程
- 通过新增配置类的方式,使用 ThreadPoolTaskExecutor配置Bean
@Configuration
// 通过注解启用异步任务
@EnableAsync
public class ThreadConfig {
@Bean
public ThreadPoolTaskExecutor executor(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//配置核心线程数
executor.setCorePoolSize(15);
//配置最大线程数
executor.setMaxPoolSize(30);
//配置队列大小
executor.setQueueCapacity(1000);
//线程的名称前缀
executor.setThreadNamePrefix("Executor-");
//线程活跃时间(秒)
//executor.setKeepAliveSeconds(60);
//等待所有任务结束后再关闭线程池
executor.setWaitForTasksToCompleteOnShutdown(true);
//设置拒绝策略
//executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//执行初始化
executor.initialize();
return executor;
}
}
- 如果只是简单的参数配置,那么直接在配置文件中加入如下配置即可
# 多线程配置
spring:
task:
execution:
pool:
core-size: 8
max-size: 256
keep-alive: 60000
queue-capacity: 256
thread-name-prefix: test
- 注意,以上通过yaml配置的方式,需要在启动类上加上多线程的启动注解。
// 通过注解启用异步任务
@EnableAsync
@SpringBootApplication
public class DbpmsApplication {
public static void main(String[] args) {
SpringApplication.run(DbpmsApplication.class, args);
}
}
3 使用多线程
- service层
public interface Test{
// 不能有返回值,如果需要返回值需要callback方法
void saveObject(String str);
}
- service实现层
// 注解不再是@Override而是@Async
@Async
public void saveObject(String str){
// 打印线程名,看是否开启了多线程
String tName=Thread.currentThread().getName();
System.err.println("调用的线程名字:"+tName);
// 可以在下方添加保存数据库操作
}
- 测试类
@Test
void testMd503() {
sysLogService.saveObject("张三");
sysLogService.saveObject("李四");
sysLogService.saveObject("王五");
sysLogService.saveObject("赵六");
}
- 打印结果
- 如果不通过@Async注解的方式声明并创建多线程,也可以直接通过注入的ThreadPoolTaskExecutor类的execute方法来创建多线程,如下所示。
@RestController
@RequestMapping("/test")
public class ThreadPoolController {
@Autowired
private SysLogService sysLogService;
// 注入线程池类
@Autowired
private ThreadPoolTaskExecutor executor;
@GetMapping("/test")
public Results test(){
// 线程异步导入数据库,会异步开始执行新增方法,同时原线程不会等待,继续执行。实现了异步操作。
executor.execute(() -> sysLogService.saveObject("张三"););
Results results = Results.success();
return results;
}
}
标签:异步,内置,SpringBoot,线程,executor,多线程,saveObject,public
From: https://www.cnblogs.com/flyingrun/p/16617067.html