1. 开启异步
@SpringBootApplication
@EnableAsync //开启异步任务
public class Application {
@Bean(name="processExecutor")
public TaskExecutor workExecutor() {
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setThreadNamePrefix("Async-");
threadPoolTaskExecutor.setCorePoolSize(10);
threadPoolTaskExecutor.setMaxPoolSize(20);
threadPoolTaskExecutor.setQueueCapacity(600);
threadPoolTaskExecutor.afterPropertiesSet();
// 自定义拒绝策略
threadPoolTaskExecutor.setRejectedExecutionHandler((r, executor) -> {
// .....
});
// 使用预设的拒绝策略
threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return threadPoolTaskExecutor;
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
复制代码
2. 配置线程池
Spring异步线程池的接口类,其实质是java.util.concurrent.Executor。
Spring 已经实现的异常线程池:
- SimpleAsyncTaskExecutor:
不是真的线程池,这个类不重用线程,每次调用都会创建一个新的线程。 - SyncTaskExecutor:
这个类没有实现异步调用,只是一个同步操作。只适用于不需要多线程的地方 - ConcurrentTaskExecutor:
Executor的适配类,不推荐使用。如果ThreadPoolTaskExecutor不满足要求时,才用考虑使用这个类 - SimpleThreadPoolTaskExecutor:
是Quartz的SimpleThreadPool的类。线程池同时被quartz和非quartz使用,才需要使用此类 - ThreadPoolTaskExecutor:
最常使用,推荐。其实质是对java.util.concurrent.ThreadPoolExecutor的包装。
3. 添加@Async注解
/**
* 异步调用返回Future
*
* @param i
* @return
*/
@Async
public Future<String> asyncInvokeReturnFuture(int i) {
log.info("asyncInvokeReturnFuture, parementer={}", i);
Future<String> future;
try {
Thread.sleep(1000 * 1);
future = new AsyncResult<String>("success:" + i);
} catch (InterruptedException e) {
future = new AsyncResult<String>("error");
}
return future;
}
复制代码
4. 通过XML文件配置
<!-- 等价于 @EnableAsync, executor指定线程池 -->
<task:annotation-driven executor="xmlExecutor"/>
<!-- id指定线程池产生线程名称的前缀 -->
<task:executor
id="xmlExecutor"
pool-size="5-25"
queue-capacity="100"
keep-alive="120"
rejection-policy="CALLER_RUNS"/>
复制代码
5. 异常处理
在调用方法时,可能出现方法中抛出异常的情况。在异步中主要有有两种异常处理方法:
- 对于方法返回值是Futrue的异步方法:
a) 一种是在调用future的get时捕获异常;
b) 在异常方法中直接捕获异常 - 对于返回值是void的异步方法:
通过AsyncUncaughtExceptionHandler处理异常
/**
* 通过实现AsyncConfigurer自定义线程池,包含异常处理
*
*/
@Service
public class MyAsyncConfigurer implements AsyncConfigurer{
private static final Logger log = LoggerFactory.getLogger(MyAsyncConfigurer.class);
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor();
threadPool.setCorePoolSize(1);
threadPool.setMaxPoolSize(1);
threadPool.setWaitForTasksToCompleteOnShutdown(true);
threadPool.setAwaitTerminationSeconds(60 * 15);
threadPool.setThreadNamePrefix("MyAsync-");
threadPool.initialize();
return threadPool;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new MyAsyncExceptionHandler();
}
/**
* 自定义异常处理类
*/
class MyAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
log.info("Exception message - " + throwable.getMessage());
log.info("Method name - " + method.getName());
for (Object param : obj) {
log.info("Parameter value - " + param);
}
}
}
}
复制代码