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 已經實現的異常線程池:
1. SimpleAsyncTaskExecutor:
不是真的線程池,這個類不重用線程,每次調用都會創建一個新的線程。
2. SyncTaskExecutor:
這個類沒有實現異步調用,只是一個同步操作。只適用於不需要多線程的地方
3. ConcurrentTaskExecutor:
Executor的適配類,不推薦使用。如果ThreadPoolTaskExecutor不滿足要求時,才用考慮使用這個類
4. SimpleThreadPoolTaskExecutor:
是Quartz的SimpleThreadPool的類。線程池同時被quartz和非quartz使用,才需要使用此類
5. 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. 異常處理
在調用方法時,可能出現方法中拋出異常的情況。在異步中主要有有兩種異常處理方法:
1. 對於方法返回值是Futrue的異步方法:
a) 一種是在調用future的get時捕獲異常;
b) 在異常方法中直接捕獲異常
2. 對於返回值是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);
}
}
}
}