启动类上添加
@EnableAsync 开启异步任务支持
1.@EnableAsync 注解
@EnableAsync
是一个 Spring Boot 中用于启动异步方法调用的注解。使用@EnableAsync
注解时,需要将其放置在一个配置类上,并且在配置类中通过@Bean
方法创建一个线程池。
/** * @Description:启动类 * * @MapperScan 使用数据源 * @EnableAsync 开启异步任务支持 */ @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, DruidDataSourceAutoConfigure.class}) @MapperScan(value = "") @EnableAsync public class ApplicationStarter extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(ApplicationStarter.class, args); } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { return builder.sources(ApplicationStarter.class); } }
1.1 配置类使用示例
AsyncTaskExecutePool 类通过 @Configuration注解来启用异步方法调用,然后在配置类中通过 继承 AsyncConfigurer 类的 getAsyncExecutor() 方法创建线程池,用于执行异步方法。
/** * 设置异步线程池配置参数 * */ @Configuration public class AsyncTaskExecutePool implements AsyncConfigurer { private Logger logger = LoggerFactory.getLogger(AsyncTaskExecutePool.class); @Autowired private TaskThreadPoolConfig config; @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(config.getCorePoolSize()); executor.setMaxPoolSize(config.getMaxPoolSize()); executor.setQueueCapacity(config.getQueueCapacity()); executor.setKeepAliveSeconds(config.getKeepAliveSeconds()); executor.setThreadNamePrefix(config.getThreadNamePrefix()); executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.initialize(); return executor; } @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { //异步任务异常处理 return new AsyncUncaughtExceptionHandler() { @Override public void handleUncaughtException(Throwable throwable, Method method, Object... objects) { logger.info("=========" + throwable.getMessage() + "=========",throwable); logger.info("exception method: " + method.getName()); } }; } }
1.2 定义异步线程池配置参数
/** * 定义异步线程池配置参数 * */ @Configuration public class TaskThreadPoolConfig { /** * 核心线程数 * */ private int corePoolSize = 5; //最大线程数 private int maxPoolSize = 50; /** * 线程池维护线程所允许的空闲时间 * */ private int keepAliveSeconds = 60; /** * 队列长度 * */ private int queueCapacity = 10000; /** * 线程名前缀 * */ private String threadNamePrefix = "preopencorpacc-AsyncTask"; public int getCorePoolSize() { return corePoolSize; } public void setCorePoolSize(int corePoolSize) { this.corePoolSize = corePoolSize; } public int getMaxPoolSize() { return maxPoolSize; } public void setMaxPoolSize(int maxPoolSize) { this.maxPoolSize = maxPoolSize; } public int getKeepAliveSeconds() { return keepAliveSeconds; } public void setKeepAliveSeconds(int keepAliveSeconds) { this.keepAliveSeconds = keepAliveSeconds; } public int getQueueCapacity() { return queueCapacity; } public void setQueueCapacity(int queueCapacity) { this.queueCapacity = queueCapacity; } public String getThreadNamePrefix() { return threadNamePrefix; } public void setThreadNamePrefix(String threadNamePrefix) { this.threadNamePrefix = threadNamePrefix; } }
2.用法1:@Async 注解
@Async
注解是一个 Spring Boot 中用于标识异步方法的注解,通过在方法上添加@Async
注解,可以让该方法在异步线程中执行。
2.1 测试Controller
DemoController 类中声明了 /demo/test 接口,接口中调用了 demoService.testError() 方法。
import com.demo.common.Result;
import com.demo.service.DemoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Resource AsynchronousService asynchronousService;
@RestController
@RequestMapping("/demo")
public class DemoController {
@Autowired
private DemoService demoService;
@CospLog
@RequestMapping("/test")
@ResponseBody
public void test() throws Exception {
try {
//异步不阻塞调取
logger.info("DemoController ", "准备开启异步任务");
asynchronousService.springAsynchronousMethod(serialNo);
logger.info("DemoController", "异步任务完成");
} catch (Exception e) {
e.printStackTrace();
//异步不阻塞调取异常
}
}
2.2 测试asynchronousServiceImpl
asynchronousServiceImpl类使用了 @Async 注解,用于异步调用,假如只配置了一个线程池,直接用 @Async 注解就会用自定义的线程池执行。
假如配置了多个线程池,用 @Async("name") 来指定使用哪个线程池,如果没有指定,会用默认的 SimpleAsyncTaskExecutor 来处理。
/** * 异步调取服务 * * @author szfh-kfwb05 * @date 20230625 */ @Service public class AsynchronousServiceImpl implements AsynchronousService { private static final Logger logger = LoggerCompManager.getLogger(LogCompConstants.INNER_COMMON_LOGGER_NAME); @Async @Override public void springAsynchronousMethod(String serialNo) {
logger.info("AsynchronousServiceImpl.springAsynchronousMethod:开始异步调取,线程名:" + Thread.currentThread().getName());
具体业务逻辑
}