今天来记录一下通过注解来实现异步操作的功能。
在这里我们需要用到两个注解:
- @EnableAsync:用来开启异步执行的监听
- @Async:用来标注异步方法
通过这两个注解可以很简单的实现异步执行方法 ,也就是开启多线程。
1、在启动类处开启添加@EnableAsync注解
package com.youyou.sso;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
@EnableScheduling
@ServletComponentScan
@SpringBootApplication
@EnableAsync
public class ApiServerApplication {
public static void main(String[] args) {
SpringApplication.run(ApiServerApplication.class, args);
}
}
2、在service处添加@Async注解
package com.youyou.sso.service.impl;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
/**
* //TODO 添加类/接口功能描述
*
* @date 2021-10-20
*/
@Service
public class AsyncTestService {
// @Async("asyncServiceExecutor")
@Async
public void test1() throws InterruptedException {
System.out.println(1);
Thread.sleep(10000);
System.out.println(2);
}
// @Async("asyncServiceExecutor")
@Async
public void test2() throws InterruptedException {
System.out.println(3);
Thread.sleep(10000);
System.out.println(4);
}
}
3、测试
package com.youyou.sso.controller;
import com.youyou.sso.bean.UserInfo;
import com.youyou.sso.service.ISsoService;
import com.youyou.sso.service.impl.AsyncTestService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
/**
* //TODO 添加类/接口功能描述
*
* @date 2021-09-06
*/
@Api(value = "异步测试", tags = "testAsync")
@RestController("")
@RequestMapping("/testAsync")
public class AsyncTestController {
@Autowired
private AsyncTestService asyncTestService;
@ApiOperation(value = "|test|")
@GetMapping("/test")
public void login() throws InterruptedException {
asyncTestService.test1();
asyncTestService.test2();
}
}
调用此接口时控制台会输出如下:
1 3 4 2
进阶内容
我们可以自己进行线程池的配置
package com.youyou.sso.config;
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;
//@Configuration
//@EnableAsync
public class ExecutorConfig {
// @Bean(name = "asyncServiceExecutor")
// @Bean
public Executor executor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//配置核心线程数
executor.setCorePoolSize(5);
//配置最大线程数
executor.setMaxPoolSize(5);
//配置队列大小
executor.setQueueCapacity(99999);
//配置线程池中的线程的名称前缀
executor.setThreadNamePrefix("async-service-");
// rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//执行初始化
executor.initialize();
return executor;
}
// @Bean(name = "asyncServiceExecutor1")
public Executor asyncServiceExecutor() {
return executor();
}
}
在bean注解的name处指定线程池的名字,并且在使用@Async注解时添加此线程池的名字就可以了
参考: