1、在启动类上加@EnableAsync注解
@EnableScheduling//开启定时任务
@EnableAsync//开启异步任务的支持
@SpringBootApplication
public class TasktestApplication {
public static void main(String[] args) {
SpringApplication.run(TasktestApplication.class, args);
}
}
2、在需要实现异步的方法上加@Async(如果加在类上,那么类中全部方法都实现异步,建议加载具体需要实现异步的方法上)
@Async
public Integer str1() {
String str = "1111111111";
try{
Thread.sleep(5000);
}catch (Exception e){
System.out.println(e.getMessage());
}
System.out.println("异步线程"+Thread.currentThread().getName()+Thread.currentThread().getId()+":"+str);
return 1;
}
3、controller层调用异步方法
@PostMapping("/add")
public Integer add(){
System.out.println("主线程开始执行:"+Thread.currentThread().getName()+Thread.currentThread().getId());
asyncService.str1();
System.out.println("主线程结束执行:"+Thread.currentThread().getName()+Thread.currentThread().getId());
return null;
}
4、测试结果,可以看到先打印了两次输出,主线程先走完,异步方法继续执行,@Async默认的线程池是SimpleAsyncTaskExecutor
主线程开始执行:http-nio-9090-exec-231
主线程结束执行:http-nio-9090-exec-231
异步线程SimpleAsyncTaskExecutor-149:1111111111
5、也可以使用自定义线程池
5.1、新建一个自定义线程池配置类
package com.task.test.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* @Date 2022/12/7
* @Author liuziyan
* @description
*/
@Configuration//让spring能扫描到
public class ThreadPoolConfig {
@Bean(name = "pool1")//交给spring管理,起名,可以配置多个线程池
public Executor createExecutor(){
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setCorePoolSize(1);//核心线程数(默认线程数)
threadPoolTaskExecutor.setMaxPoolSize(5);//最大线程数
threadPoolTaskExecutor.setKeepAliveSeconds(60);//允许线程空闲时间(单位:默认为秒)
threadPoolTaskExecutor.setQueueCapacity(200);//缓冲队列数
threadPoolTaskExecutor.setThreadNamePrefix("lzyThread");//线程池名前缀
//线程池对拒绝任务的处理策略
threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
threadPoolTaskExecutor.initialize();
return threadPoolTaskExecutor;
}
@Bean(name = "pool2")
public Executor createExecutor2(){
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setCorePoolSize(1);
threadPoolTaskExecutor.setMaxPoolSize(5);
threadPoolTaskExecutor.setKeepAliveSeconds(60);
threadPoolTaskExecutor.setQueueCapacity(200);
threadPoolTaskExecutor.setThreadNamePrefix("lzyThread2");
threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
threadPoolTaskExecutor.initialize();
return threadPoolTaskExecutor;
}
}
5.2、方法上用到@Async注解需要指定线程池的Bean名字(如果配置了一个线程池,直接用@Async就会用自定义线程池执行,如果有多个线程池配置,需要指定自定义线程池的Bean名字,否则@Async会使用默认的线程池SimpleAsyncTaskExecutor处理)
@Async("pool1")
public Integer str1() {
String str = "1111111111";
try{
Thread.sleep(5000);
}catch (Exception e){
System.out.println(e.getMessage());
}
System.out.println("异步线程"+Thread.currentThread().getName()+Thread.currentThread().getId()+":"+str);
return 1;
}
5.3、执行结果,可以看到,线程的名字是自定义线程池配置的名字
主线程开始执行:http-nio-9090-exec-335
主线程结束执行:http-nio-9090-exec-335
异步线程lzyThread151:1111111111
导致注解不生效的原因有几种:
1、异步方法使用static修饰
2、异步方法类没有使用@Service注解(或其他注解)导致spring无法扫描到异步类
3、controller中需要使用@Autowired或@Resource等注解自动注入异步类,不能自己手动new对象