有3年工作经验的小伙伴被问到这样一个面试题,Spring异步调用的实现方式有哪些?今天,我就把我的理解分享给大家。在Spring中,实现异步调用主要有三种方式,分别是注解、内置线程池和自定义线程池。1、注解方法可以为配置类和方法添加特定的注解。首先在配置类中添加@EnableAsync开启异步注解,如代码所示:@EnableAsync//开启异步支持@ConfigurationpublicclassAppConfig{}然后,使用@Async注解标记需要异步执行的方法,如代码所示:@AsyncvoiddoSomething(){//这将异步运行}@AsyncvoiddoSomething(Strings){//这将异步运行}@AsyncFuturereturnSomething(inti){//这将异步运行}使用@Async标记的异步方法可以带参数和返回值。返回值类型必须是java.util.concurrent.Future或其子类,可以是以下三种类型:1)原生JavaAPI提供的Future。2)ListenableFuture后者由Spring提供的AsyncResult。3)Java8提供的CompletableFuture。需要注意的是@Async默认会使用SimpleAsyncTaskExecutor来执行,这个线程池不会复用线程。因此,通常要使用异步处理,我们都会自定义线程池。2、内置线程池方法可以使用Spring内置的线程池实现异步调用,比如ThreadPoolTask??Executor、SimpleAsyncTaskExecutor。Spring提供了许多TaskExecutor的内置实现。下面简单介绍一下内置的五种线程池。1)SimpleAsyncTaskExecutor:不复用线程,每次调用都会启动一个新的线程。2)ConcurrentTaskExecutor:是JavaAPI中Executor实例的适配器。3)ThreadPoolTask??Executor:这个线程池是最常用的。它为配置公开bean属性并将其包装在TaskExecutor中。4)WorkManagerTaskExecutor:基于CommonJWorkManager实现,是Spring上下文中WebLogic或WebSphere中设置CommonJ线程池的工具类。5)DefaultManagedTaskExecutor:主要用于支持JSR-236兼容的运行环境。它使用JNDI获取ManagedExecutorService作为CommonJWorkManager的替代。通常,ThreadPoolTask??Executo是最常用的。只要ThreadPoolTask??Executor不能满足要求,就可以使用ConcurrentTaskExecutor。如果在代码中声明了多个线程池,Spring会默认按照以下搜索顺序调用线程池:首先,检查上下文中唯一的TaskExecutorBean。第二步,勾选名为“taskExecutor”的ExecutorBean。第三步,如果以上都无法处理,则使用SimpleAsyncTaskExecutor来执行。3.自定义线程池方式可以通过实现AsyncConfigurer接口或者直接继承AsyncConfigurerSupport类来自定义线程池。但是,非完全托管bean和完全托管bean的实现略有不同。首先,看一下非完全托管的SpringBean。实现如代码所示:executor.setCorePoolSize(7);executor.setMaxPoolSize(42);executor.setQueueCapacity(11);executor.setThreadNamePrefix("MyExecutor-");executor.initialize();//手动初始化returnexecutor;}@OverridepublicAsyncUncaughtExceptionHandlergetAsyncUncaughtExceptionHandler(){返回新的MyAsyncUncaughtExceptionHandler();}}在此代码中,ThreadPoolTask??Executor不是完全托管的Springbean。然后,再看完全托管的SpringBean,如代码所示:executor.setCorePoolSize(7);executor.setMaxPoolSize(42);executor.setQueueCapacity(11);executor.setThreadNamePrefix("MyExecutor-");//executor.initialize();//无需手动调用returnexecutor;}@OverridepublicAsyncUncaughtExceptionHandlergetAsyncUncaughtException(){返回新的MyAsyncUncaughtExceptionHandler();}}只要在异步方法中加上@Bean注解,就不需要手动调用线程池的initialize()方法,Bean初始化后会自动调用。需要注意的是,在同级类中直接调用异步方法是无法实现异步的。以上就是我对Spring实现异步调用的理解。