@Async的使用

@Async 是Spring Framework提供的一个注解,用于在Spring应用程序中异步执行方法。当需要执行一个耗时的任务,而不想阻塞主线程时,这个方法就非常有用。以下是如何使用@Async以及一些注意事项:

如何使用@Async

启用异步支持

在启动类上添加@EnableAsync注解,以启用异步方法执行的能力。

@EnableAsync
public class MainApplication {
    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class, args);
    }
}

定义异步方法

在任何@Component@Service注解的类中,使用@Async注解声明一个异步方法。

@Service
public class AsyncService {
    
    @Async(executor = "taskExecutor")
    public void executeAsyncTask() {
        // 执行耗时操作的代码
    }

    @Async(executor = "taskExecutor")
    // 异步方法通常不返回结果,因为调用者不会等待结果。如果需要返回结果,可以使用Future或CompletableFuture。
    public CompletableFuture<ResultType> executeAsyncTaskWithResult() {
        // 执行耗时操作并返回结果
    }
    
}

调用异步方法

可以像调用普通方法一样调用异步方法,Spring 会在一个单独的线程中执行该方法。

@Service
public class SomeService {
    
    @Resource
    private AsyncService asyncService;

    public void someMethod() {
        asyncService.executeAsyncTask();
        // 这个方法会立即返回,executeAsyncTask() 在另一个线程中执行。
    }
}

配置异步执行器(可选)

可以自定义用于执行异步方法的Executor,如果不配置,Spring默认使用一个简单的Executor

@Bean(name = "taskExecutor")
public Executor taskExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    // 设置线程池的基本线程数(核心池大小),即即使当前没有任务执行,线程池也会保持10个线程处于活跃状态。
    executor.setCorePoolSize(10);
    // 设置线程池中允许的最大线程数。如果任务数量超过核心池大小,线程池会创建新的线程来处理任务,直到达到这个最大值。
    executor.setMaxPoolSize(20);
    // 设置等待执行的任务队列的容量。如果线程池中的线程都处于活跃状态,新提交的任务将被放入这个队列中等待执行。
    executor.setQueueCapacity(100);
    // 初始化线程池执行器。在Spring的上下文中,通常不需要显式调用initialize()方法,因为Spring会自动初始化Bean。但在这里调用可以确保在返回执行器之前,执行器已经被正确地设置和初始化。
    executor.initialize();
    return executor;
}

如果希望所有标记了<font style="color:rgb(6, 6, 7);">@Async</font>的方法都使用同一个<font style="color:rgb(6, 6, 7);">taskExecutor</font>,可以在配置类中设置默认的执行器。

@Configuration
@EnableAsync
public class AsyncConfig extends AsyncConfigurationSupport {

    @Bean(name = "taskExecutor")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 设置线程池的基本线程数(核心池大小),即即使当前没有任务执行,线程池也会保持10个线程处于活跃状态。
        executor.setCorePoolSize(10);
        // 设置线程池中允许的最大线程数。如果任务数量超过核心池大小,线程池会创建新的线程来处理任务,直到达到这个最大值。
        executor.setMaxPoolSize(20);
        // 设置等待执行的任务队列的容量。如果线程池中的线程都处于活跃状态,新提交的任务将被放入这个队列中等待执行。
        executor.setQueueCapacity(100);
        // 初始化线程池执行器。在Spring的上下文中,通常不需要显式调用initialize()方法,因为Spring会自动初始化Bean。但在这里调用可以确保在返回执行器之前,执行器已经被正确地设置和初始化。
        executor.initialize();
        return executor;
    }

    @Override
    public Executor getAsyncExecutor() {
        return taskExecutor();
    }
    
}

注意事项

  1. @Async注解的方法必须在Spring管理的Bean中调用。
  2. 异步方法不能用于构造函数、@PostConstruct方法或@PreDestroy方法。
  3. 异步方法抛出的异常不会传播给调用者,需要在异步方法内部处理异常。
  4. ****异步方法不支持当前的事务传播行为,因为它们在不同的线程中执行。
  5. 如果异步方法需要返回值,应使用FutureCompletableFuture作为返回类型。
  6. ****确保异步方法中使用的共享资源是线程安全的。
  7. 如果不配置自定义的Executor,Spring将使用默认的SimpleAsyncTaskExecutor,这可能会导致线程创建开销。
  8. ****异步方法可能会使调试和日志记录变得复杂,因为它们在不同的线程中执行。
  9. 考虑实现错误处理机制,比如使用@Async注解的noResultException属性来指定当异步执行出现异常时应该抛出的异常类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

付聪1210

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值