Spring Async 使用及优化

1. Spring Async 使用及优化

1.1. 开启异步支持

使用 @EnableAsync 注解开启异步支持,Spring 将对使用 @Async 注释的方法包装成一个 FutureTask,默认由 SimpleAsyncTaskExecutor 线程池执行。

@Configuration
@EnableAsync
public class AsyncConfiguration {
    
}

1.2. 异步方法

在方法上使用 @Async 注解即可,方法将在异步线程中被调用。
这里有两点需要注意

  1. 只能是 public 公有方法。
  2. 在同一个类中调用异步方法将不起效果。

1.2.1. 无返回值的异步方法

@Async
public void asyncWithoutResult() {
    return;
}

1.2.2. 有返回值的异步方法

@Async
public Future<String> asyncWithResult() {
    return AsyncResult.forValue("OK");
}

@Async
public CompletableFuture<String> asyncWithResult() {
    return AsyncResult.forValue("OK").completable();
}

1.3. 线程池优化

默认情况下,Spring 使用 SimpleAsyncTaskExecutor 线程池异步执行任务,这个线程池每次执行任务都会创建一个新线程,开销很大并且容易造成 OOM,因此有必要使用自定义线程池来执行异步任务。

核心源码:

protected void doExecute(Runnable task) {
    Thread thread = (this.threadFactory != null ? this.threadFactory.newThread(task) : createThread(task));
    thread.start();
}

1.3.1. 方法级线程池

@Async 注解可以指定要使用的线程池。

  1. 自定义线程池 Bean
@Configuration
@EnableAsync
public class AsyncConfiguration {
    @Bean
    public Executor asyncExecutor() {
        int availableProcessors = Runtime.getRuntime().availableProcessors();
        return ExecutorBuilder.create()
                .setCorePoolSize(availableProcessors + 1)
                .setMaxPoolSize(availableProcessors + 1)
                .useArrayBlockingQueue(1024)
                .setThreadFactory(ThreadFactoryBuilder.create().setNamePrefix("async-").build())
                .build();
    }
}
  1. @Async 注解指定要使用的线程池 Bean
@Service
public class AsyncService {
    @Async("asyncExecutor")
    public void asyncWithoutResult() {
        return;
    }
}

1.3.2. 全局线程池

实现 AsyncConfigurer 接口指定全局线程池。

@Configuration
@EnableAsync
public class AsyncConfiguration implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
        int availableProcessors = Runtime.getRuntime().availableProcessors();
        return ExecutorBuilder.create()
                .setCorePoolSize(availableProcessors + 1)
                .setMaxPoolSize(availableProcessors + 1)
                .useArrayBlockingQueue(1024)
                .setThreadFactory(ThreadFactoryBuilder.create().setNamePrefix("async-").build())
                .build();
    }
}

1.4. 异常处理

实现 AsyncConfigurer 接口指定异常处理逻辑。

@Slf4j
@Configuration
@EnableAsync
public class AsyncConfiguration implements AsyncConfigurer {
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return (ex, method, params) -> log.error("Spring Async Error. method: {}, params: {}", method, params, ex);
    }
}
posted @ 2024-05-28 16:18  Jason207010  阅读(211)  评论(0)    收藏  举报