Spring中使用@Async来实现异步调用
Spring中使用@Async来实现异步调用
1.关于异步调用
-
同步就是整个处理过程顺序执行,当各个过程都执行完毕,并返回结果。 异步调用则是只是发送了调用的指令,调用者无需等待被调用的方法完全执行完毕;而是继续执行下面的流程。 在Spring中,基于@Async标注的方法,称之为异步方法;这些方法将在执行的时候,将会在独立的线程中被执行,调用者无需等待它的完成,即可继续其他的操作。
2.@Async的使用
开启@Async
-
使用@EnableAsync注解可以在项目中开启@Async。
具体使用@Async
有两种方式来使用,可以选择有返回值和无返回值。
-
无返回值
@Async public void returnWithVoid() { }
-
有返回值
@Async public Future<String> returnWithString() { return "hello world"; }
可以看到,这里使用@Async时没有设置参数,默认情况下,Spring使用SimpleAsyncTaskExecutor去执行这些异步方法(此执行器没有限制线程数)。我们也可以自定义线程池, 在不同的异步调用间做到资源隔离。
3.线程池的配置
一个项目不推荐配置一个线程池,这样若是某些业务出现异常时,会影响到整个项目的健壮性。故根据业务,为不同的业务配置不同参数的数据库连接池。
import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.Executor; import java.util.concurrent.ThreadPoolExecutor; @Configuration public class ExecutorConfig { /** * 核心线程数:线程池创建时候初始化的线程数 */ @Value("${async-executor.core.pool.size}") private int asyncCorePoolSize; /** * 最大线程数:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程 */ @Value("${async-executor.max.pool.size}") private int asyncMaxPoolSize; /** * 缓冲队列200:用来缓冲执行任务的队列 */ @Value("${async-executor.queue.capacity}") private int asyncQueueCapacity; /** * 允许线程的空闲时间(单位:秒):当超过了核心线程出之外的线程在空闲时间到达之后会被销毁 */ @Value("${async-executor.keepalive.Seconds}") private int asyncKeepAliveSeconds; /** * 线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池 */ @Value("${async-executor.thread.name.prefix}") private String asyncThreadNamePrefix; @Bean public Executor asyncServiceExecutor() { ThreadPoolTaskExecutor threadPoolTaskExecutor = new VisiableThreadPoolTaskExecutor(); threadPoolTaskExecutor.setCorePoolSize(asyncCorePoolSize); threadPoolTaskExecutor.setAllowCoreThreadTimeOut(true); threadPoolTaskExecutor.setMaxPoolSize(asyncMaxPoolSize); threadPoolTaskExecutor.setQueueCapacity(asyncQueueCapacity); threadPoolTaskExecutor.setKeepAliveSeconds(asyncKeepAliveSeconds); threadPoolTaskExecutor.setThreadNamePrefix(asyncThreadNamePrefix); //拒绝策略 threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy()); threadPoolTaskExecutor.initialize(); return threadPoolTaskExecutor; } }
我们可以 @Async(“asyncServiceExecutor”) 以这样的方式来指明线程池进行异步调用。