通常,如果我们要在程序中做一个耗时的操作(例如调用其他外部模块),一般会通过异步的方式执行。
有这2种方法:
- 自行生成线程池ThreadPoolExecutor,提交任务执行
- 更方便地,使用Spring @Async注解,修饰在需要异步执行的方法上
对于第一种方法的异常处理,楼主已经在Java子线程中的异常处理(通用)这篇文章中介绍了,也就是提交任务后获取到Future对象,通过future.get()获取返回值的时候能够捕获到ExcecutionException。
对于Spring @Async注解的方法,如何进行异常处理呢?楼主想到了2种方法。
方法一:配置AsyncUncaughtExceptionHandler(对于无返回值的方法)
通过AsyncConfigurer自定义线程池,以及异常处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| @Configuration @EnableAsync public class SpringAsyncConfiguration implements AsyncConfigurer { private static final Logger logger = LoggerFactory.getLogger(getClass());
@Bean @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(8); executor.setMaxPoolSize(16); executor.setQueueCapacity(64); executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.setThreadNamePrefix("SpringAsyncThread-");
return executor; }
@Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return new SpringAsyncExceptionHandler(); }
class SpringAsyncExceptionHandler implements AsyncUncaughtExceptionHandler { @Override public void handleUncaughtException(Throwable throwable, Method method, Object... obj) { logger.error("Exception occurs in async method", throwable.getMessage()); } } }
|
方法二:通过AsyncResult捕获异常(对于有返回值的方法)
如果异步方法有返回值,那就应当返回AsyncResult类的对象,以便在调用处捕获异常。
因为AsyncResult是Future接口的子类,所以也可以通过future.get()获取返回值的时候捕获ExcecutionException。
异步方法:
1 2 3 4 5 6 7 8 9 10 11 12
| @Service public class AsyncService {
@Async public AsyncResult<String> asyncMethodWithResult() {
return new AsyncResult("hello"); }
}
|
调用处捕获异常:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class Test { private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired AsyncService asyncService;
public void test() { try { Future future = asyncService.asyncMethodWithResult(); future.get(); } catch (ExecutionException e) { logger.error("exception occurs", e); } catch (InterruptedException e) { logger.error("exception occurs", e); } } }
|