异步方法
在配置类上配置 @EnableAsync
注解开启异步处理。
在方法上加上注解@Async
将该方法标记为异步任务。
用法和FutureTask+Callable差不多,可以返回AsyncResult类型,它是Future的一个实现类。
例:
@Async
public Future<String> asyncTask() throws InterruptedException{
Thread.sleep(2000);
return new AsyncResult<>("任务完成");
}
异步线程池
如果一直使用@Async
不配合线程池,会消耗很多资源,效率变低,Spring中有一个AsyncConfigurer接口,可以通过它配置线程池。
public interface AsyncConfigurer {
//获取线程池
@Nullable
default Executor getAsyncExecutor() {
return null;
}
//异步异常处理器
@Nullable
default AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return null;
}
}
于是我们可以创建一个配置类,在这里面写实现,@EnableAsync
注解放到这个配置类上面可以增加可读性。
@Configuration
@Slf4j
public class AsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
log.info("正在创建线程池");
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(30);
executor.setQueueCapacity(2000);
executor.setThreadNamePrefix("global-thread-pool-");
executor.initialize();
return executor;
}
}
这样创建的线程池是全局的,也就是说默认使用@Async
标注的方法都会从这个线程池中取线程,我们可以测试一下:
@Async
public void testPool() throws InterruptedException {
System.out.println(Thread.currentThread().getName());
Thread.sleep(1000);
}
输出:
global-thread-pool-1
如果我们想让它灵活度更高一点,可以往IoC容器中注入一些Executor,使用@Async("")
的value来指定一个要使用的线程池的bean名称。
例如,给配置类中添加注入Executor bean的方法:
@Configuration
@Slf4j
public class AsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
log.info("正在创建线程池");
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(30);
executor.setQueueCapacity(2000);
executor.setThreadNamePrefix("global-thread-pool-");
executor.initialize();
return executor;
}
@Bean("bigExecutor")
public Executor getBigExecutor() {
log.info("正在创建线程池");
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(50);
executor.setMaxPoolSize(80);
executor.setQueueCapacity(80);
executor.setThreadNamePrefix("big-thread-pool-");
executor.initialize();
return executor;
}
}
指定使用线程池:
@Async("bigExecutor")
public void testBigPool() throws InterruptedException {
System.out.println(Thread.currentThread().getName());
Thread.sleep(1000);
}
原创文章,作者:彭晨涛,如若转载,请注明出处:https://www.codetool.top/article/springboot%e5%af%b9%e5%bc%82%e6%ad%a5%e4%bb%bb%e5%8a%a1%e7%9a%84%e6%94%af%e6%8c%81/