您的位置:

深度解析Spring异步注解

一、Spring异步注解阻塞

Spring异步注解是提高程序效率的重要手段之一,但是如果不合理使用,也会带来阻塞问题。比如,如果在使用Spring异步注解时,注解了过多的方法或者使用了分段锁,就会导致性能反而下降。

@Async
public Future<Void> computeAsync() {
    return CompletableFuture.completedFuture(null);
}

为了避免Spring异步注解阻塞,可以采取以下措施:

1.合理控制异步请求的个数,以充分利用资源提高效率;

2.使用分布式锁代替分段锁;

3.使用异步队列等辅助类提高处理效率。

二、Spring异步注解有什么弊端

Spring异步注解虽然可以提高程序效率,但也存在一些弊端:

1.异步调用可能导致程序执行顺序与代码编写顺序不一致,导致程序逻辑异常;

2.当异步执行的任务执行时间过长,可能导致线程池的拥堵等问题;

3.因为异步调用是在新的线程中执行,所以在异步调用过程中,线程上下文不能被当做请求上下文传递。

三、Spring异步注解怎么实现

Spring异步注解的实现主要依赖于两个核心类:

1. AsyncAnnotationBeanPostProcessor:用于处理Bean中标注@Async注解的方法,生成异步执行代理;

2. AsyncExecutionInterceptor:用于创建执行异步任务的Runnable实例。

具体实现方法如下:

@Configuration
@EnableAsync
public class AsyncConfig extends AsyncConfigurerSupport {
 
    @Bean
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(2000);
        executor.setThreadNamePrefix("async-thread-");
        executor.initialize();
        return executor;
    }
}

@Service
public class AsyncService {
 
    @Async
    public Future<String> doSomeLongOperation() {
        //long operation
        return CompletableFuture.completedFuture(result);
    }
}

public class AsyncAction {
    private AsyncService asyncService;
    //调用异步方法并获得结果
    public void doAction() {
        Future<String> result = asyncService.doSomeLongOperation();
        //...
    }
}

四、Spring异步注解原理

Spring异步注解的原理是通过AOP技术,对被@Async注解标记的方法,进行拦截并创建异步代理,然后将异步调用转发到线程池执行,最后返回Future对象以便其它方法继续执行。

五、Spring异步注解不生效

Spring异步注解不生效的原因主要有以下几点:

1.项目没有开启异步执行支持,需要@EnableAsync注解

2.方法没有被public修饰;

3.在同一个类中调用异步方法,没有使用self调用,导致代理失效。

六、Spring开启异步注解

Spring开启异步注解需要通过@EnableAsync注解来开启,并且需要通过@Configuration类中覆盖AsyncConfigurerSupport类的getAsyncExecutor方法来配置线程池(可选)。

@Configuration
@EnableAsync
public class AsyncConfig extends AsyncConfigurerSupport {
 
    @Bean
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(2000);
        executor.setThreadNamePrefix("async-thread-");
        executor.initialize();
        return executor;
    }
}

七、Spring异步注解是什么

Spring异步注解是标记一个方法会被异步调用的注解。在方法上加上@Async注解,使其可以被多线程执行,从而提高程序的效率。

八、Spring异步注解使用场景

Spring异步注解非常适合处理长时间耗时的任务,例如大文件读取、大数据处理、网络IO等。

九、Spring异步注解事务不起作用

Spring事务管理默认是基于线程的,即同一个线程中的各个事务共享同一个连接和事务,但是如果在异步调用中开启了新的线程,那么事务就无法在新线程中被识别,因此在使用Spring异步注解时,需要注意事务的传播属性,可以在注解中指定PROPAGATION_REQUIRES_NEW级别的传播行为来实现异步调用时的事务管理。

@Service
public class AsyncService {
 
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @Async
    public Future<String> doSomeLongOperation() {
        //long operation
        return CompletableFuture.completedFuture(result);
    }
}

附:SpringBoot异步注解示例

对于SpringBoot项目,使用异步注解的方法与普通Spring项目一致,只需要在SpringBoot的启动类中使用@EnableAsync注解,然后在需要异步执行的方法上使用@Async注解即可。

@SpringBootApplication
@EnableAsync
public class Application {
    //...
}