Spring中的@Async注解的使用示例

文章介绍了在Springboot中使用@Async注解实现异步任务的方法,强调了默认SimpleAsyncTaskExecutor可能导致的内存问题,并展示了如何配置自定义线程池以优化性能。通过ThreadPoolTaskExecutor设置核心线程数、最大线程数和队列容量,以及处理线程上下文切换的问题。
摘要由CSDN通过智能技术生成

在Springboot中通常会使用@Async注解开启一个异步线程来执行异步任务,本文主要讨论该注解的使用示例及在使用过程中的注意事项。

@Async
public void asyncMethod(){
    //do something
}

通常情况下直接使用@EnableAsync和@Async注解就可以实现任务的异步执行,但如果未配置@Async注解的value属性默认会使用内部的SimpleAsyncTaskExecutor来创建线程并执行任务。默认情况下该线程池是来一个任务创建一个线程,若系统中不断的创建线程,最终会导致系统占用内存过高,引发OutOfMemoryError错误。

针对线程创建问题,SimpleAsyncTaskExecutor提供了限流机制,通过concurrencyLimit属性来控制开关,当concurrencyLimit>=0时开启限流机制,默认关闭限流机制即concurrencyLimit=-1,当关闭情况下,会不断创建新的线程来处理任务。基于默认配置SimpleAsyncTaskExecutor并不是严格意义的线程池,达不到线程复用的目的。

使用自定义线程池示例如下:

//配置自定义的线程池
@Configuration
@EnableAsync
public class AppConfig {
    public static final String ASYNC_EXECUTOR_NAME = "asyncExecutor";

    @Bean(name = ASYNC_EXECUTOR_NAME)
    public Executor asyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

        executor.setCorePoolSize(3);
        executor.setMaxPoolSize(5);
        executor.setQueueCapacity(100);
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setThreadNamePrefix("AsyncThread-");
        executor.setTaskDecorator(runnable -> {
            RequestAttributes context = RequestContextHolder.getRequestAttributes();
            return () -> {
                try {
                    RequestContextHolder.setRequestAttributes(context);
                    runnable.run();
                } finally {
                    RequestContextHolder.resetRequestAttributes();
                }
            };
        });

        return executor;
    }
}



//使用自定义的线程池
@Async(AppConfig.ASYNC_EXECUTOR_NAME)
public void asyncMethod(){
    //do something
}

以上就定义了一个名为asyncExecutor的线程池,并设置了其corePoolSize、maxPoolSize、线程名称等相关的参数。在实际使用时还会遇到线程上下文切换的问题,需要对属性值进行复制:

public class ContextCopyingDecorator implements TaskDecorator {
    public Runnable decorate(final Runnable runnable) {
        final RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();
        return () -> {
            try {
                RequestContextHolder.setRequestAttributes(attributes);
                runnable.run();
            } finally {
                RequestContextHolder.resetRequestAttributes();
            }
        };
    }
}

总结:@Async是Spring中定义异步任务经常使用的注解,实际使用过程中通常会自定义其线程池,设置单独的线程名称以更方便地排查问题。同时在Request请求过程中线程切换,需要对相关属性值进行复制。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值