SpringBoot-(11)async异步的配置和使用

it2026-06-19  8

async异步的配置和使用

异步调用,对应的是同步调用。

同步调用:指程序按照 定义顺序 依次执行,每一行程序都必须等待上一行程序执行完成之后才能执行;异步调用:指程序在顺序执行时,不等待异步调用的语句返回结果,就执行后面的程序。

在 Spring Framework 的 Spring Task 模块,提供了 @Async 注解,可以添加在方法上,自动实现该方法的异步调用。因此不需要特别引入依赖,只要引入springboot的依赖即可。

1、application.yml配置

task: # Spring 执行器配置,对应 TaskExecutionProperties 配置类。对于 Spring 异步任务,会使用该执行器。 execution: thread-name-prefix: task- # 线程池的线程名的前缀。默认为 task- ,建议根据自己应用来设置 pool: # 线程池相关 core-size: 8 # 核心线程数,线程池创建时候初始化的线程数。默认为 8 。 max-size: 20 # 最大线程数,线程池最大的线程数,只有在缓冲队列满了之后,才会申请超过核心线程数的线程。默认为 Integer.MAX_VALUE keep-alive: 60s # 允许线程的空闲时间,当超过了核心线程之外的线程,在空闲时间到达之后会被销毁。默认为 60 秒 queue-capacity: 200 # 缓冲队列大小,用来缓冲执行任务的队列的大小。默认为 Integer.MAX_VALUE 。 allow-core-thread-timeout: true # 是否允许核心线程超时,即开启线程池的动态增长和缩小。默认为 true 。 shutdown: await-termination: true # 应用关闭时,是否等待定时任务执行完成。默认为 false ,建议设置为 true await-termination-period: 60 # 等待任务完成的最大时长,单位为秒。默认为 0 ,根据自己应用来设置

2、Application

创建 Application.java类,配置 @SpringBootApplication 注解。

@SpringBootApplication @EnableAsync // 开启 @Async 的支持 public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }

在类上添加 @EnableAsync 注解,启用异步功能。

3、AsyncConfig类

创建 AsyncConfig类,配置异常处理器

@Configuration @EnableAsync // 开启 @Async 的支持 public class AsyncConfig implements AsyncConfigurer { @Autowired private GlobalAsyncExceptionHandler exceptionHandler; @Override public Executor getAsyncExecutor() { return null; } @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return exceptionHandler; } }

配置类里使用了@EnableAsync,Application类中就可以省略@EnableAsync注释

4、GlobalAsyncExceptionHandler 全局异常处理类

创建 GlobalAsyncExceptionHandler 类,全局统一的异步调用异常的处理器。

/** * AsyncUncaughtExceptionHandler 只能拦截返回类型非 Future 的异步调用方法 */ @Component public class GlobalAsyncExceptionHandler implements AsyncUncaughtExceptionHandler { private final Logger logger = LoggerFactory.getLogger(getClass()); @Override public void handleUncaughtException(Throwable ex, Method method, Object... params) { logger.error("[handleUncaughtException][method({}) params({}) 发生异常]", method, params, ex); } }

AsyncUncaughtExceptionHandler 只能拦截返回类型非 Future 的异步调用方法。

5、AsyncService类

在方法前加@Async注释,即启用了异步方法。

@Slf4j @Service public class AsyncService extends AbstractService{ @Async public Integer execute01Async() { return this.execute01(); } @Async public Integer execute02Async() { return this.execute02(); } @Async public Future<Integer> execute01AsyncWithFuture() { return AsyncResult.forValue(this.execute01()); } @Async public Future<Integer> execute02AsyncWithFuture() { return AsyncResult.forValue(this.execute02()); } @Async public ListenableFuture<Integer> execute01AsyncWithListenableFuture() { try { return AsyncResult.forValue(this.execute02()); } catch (Throwable ex) { return AsyncResult.forExecutionException(ex); } } public Integer execute01() { log.info("[execute01]"); sleep(10); return 1; } public Integer execute02() { log.info("[execute02]"); sleep(5); return 2; } private static void sleep(int seconds) { try { Thread.sleep(seconds * 1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } @Async public Integer zhaoDaoNvPengYou(Integer a, Integer b) { throw new RuntimeException("程序员不需要女朋友"); } }

往往会出现主线程执行完成,异步方法还未执行。

在一些业务场景中,我们希望达到异步调用的效果,同时主线程阻塞等待异步调用的结果。示例中增加 #execute01() 和 #execute02() 的异步调用,并返回 Future 对象

6、测试类

@Slf4j @RunWith(SpringRunner.class) @SpringBootTest(classes = DemoApplication.class) public class DemoApplicationTests { @Autowired private AsyncService asyncService; @Test public void task01() { long now = System.currentTimeMillis(); log.info("[task01][开始执行]"); asyncService.execute01(); asyncService.execute02(); log.info("[task01][结束执行,消耗时长 {} 毫秒]", System.currentTimeMillis() - now); } @Test public void task02() { long now = System.currentTimeMillis(); log.info("[task02][开始执行]"); asyncService.execute01Async(); asyncService.execute02Async(); log.info("[task02][结束执行,消耗时长 {} 毫秒]", System.currentTimeMillis() - now); } @Test public void task03() throws ExecutionException, InterruptedException { long now = System.currentTimeMillis(); log.info("[task03][开始执行]"); // 执行任务 Future<Integer> execute01Result = asyncService.execute01AsyncWithFuture(); Future<Integer> execute02Result = asyncService.execute02AsyncWithFuture(); // 阻塞等待结果 execute01Result.get(); execute02Result.get(); log.info("[task03][结束执行,消耗时长 {} 毫秒]", System.currentTimeMillis() - now); } @Test public void task04() throws ExecutionException, InterruptedException { long now = System.currentTimeMillis(); log.info("[task04][开始执行]"); // 执行任务 ListenableFuture<Integer> execute01Result = asyncService.execute01AsyncWithListenableFuture(); log.info("[task04][execute01Result 的类型是:({})]",execute01Result.getClass().getSimpleName()); execute01Result.addCallback(new SuccessCallback<Integer>() { // 增加成功的回调 @Override public void onSuccess(Integer result) { log.info("[onSuccess][result: {}]", result); } }, new FailureCallback() { // 增加失败的回调 @Override public void onFailure(Throwable ex) { log.info("[onFailure][发生异常]", ex); } }); execute01Result.addCallback(new ListenableFutureCallback<Integer>() { // 增加成功和失败的统一回调 @Override public void onSuccess(Integer result) { log.info("[onSuccess][result: {}]", result); } @Override public void onFailure(Throwable ex) { log.info("[onFailure][发生异常]", ex); } }); // 阻塞等待结果 execute01Result.get(); log.info("[task04][结束执行,消耗时长 {} 毫秒]", System.currentTimeMillis() - now); } @Test public void testZhaoDaoNvPengYou() throws InterruptedException { asyncService.zhaoDaoNvPengYou(1, 2); // sleep 1 秒,保证异步调用的执行 Thread.sleep(1000); } }

task01的结果:

task02的结果:

task03的结果:

task04的结果:

testZhaoDaoNvPengYou的结果:

最新回复(0)