赞
踩
- @Configuration
- public class ThreadPoolConfig {
-
- public static ThreadPoolExecutor getThreadPoolExecutor() {
- int availableProcessors = Runtime.getRuntime().availableProcessors();
- return new ThreadPoolExecutor(
- availableProcessors,
- availableProcessors,
- 0L,
- TimeUnit.MILLISECONDS,
- new LinkedBlockingQueue<>(9999),
- new ThreadFactoryBuilder().setNameFormat("custom-thread-pool-%d").build(),
- new ThreadPoolExecutor.CallerRunsPolicy());
- }
-
- }

写一个存在异常的程序,让其异步执行
- public static final ThreadPoolExecutor CUSTOM_THREAD_POOL = ThreadPoolConfig.getThreadPoolExecutor();
-
- /**
- * 异步执行异常测试
- */
- @ApiOperation(value = "异步执行异常测试", code = 800)
- @GetMapping("/asyncException")
- public ResponseData<Object> asyncException() {
- try {
- try {
- CompletableFuture.runAsync(() -> {
- int i = 1 / 0;
- }, CUSTOM_THREAD_POOL);
- } catch (Exception e) {
- log.error("异常信息: " + e.getMessage(), e);
- throw new BusinessException(e.getMessage());
- }
- return new ResponseData<>(StatusCodeEnum.SUCCESS_CODE.getStatusCode(), "操作成功");
- } catch (Exception e) {
- return new ResponseData<>(StatusCodeEnum.ERROR_CODE.getStatusCode(), "操作失败:" + e.getMessage());
- }
- }

结果:接口返回成功,控制台没有打印错误信息。
- // join方法获取异常信息: 将异步线程中发生的异常信息抛到主线程, 这样异常可被主线程捕获
- try {
- CompletableFuture.runAsync(() -> {
- int i = 1 / 0;
- }, CUSTOM_THREAD_POOL).join();
- } catch (Exception e) {
- log.error("外层异常信息: " + e.getMessage(), e);
- throw new BusinessException(e.getMessage());
- }
结果:接口返回失败,控制台打印异常日志。
异步方法中get()是阻塞的,在使用时要设置超时时间。
- // get方法获取异常信息: 将异步线程中发生的异常信息抛到主线程, 这样异常可被主线程捕获
- try {
- CompletableFuture.runAsync(() -> {
- int i = 1 / 0;
- }, CUSTOM_THREAD_POOL).get(2, TimeUnit.SECONDS);
- } catch (Exception e) {
- log.error("外层异常信息: " + e.getMessage(), e);
- throw new BusinessException(e.getMessage());
- }
结果:接口返回成功,控制台打印异常信息。
- // exceptionally获取异常信息: 异常是存在于异步当中的, 不能被主线程捕获
- try {
- CompletableFuture.runAsync(() -> {
- int i = 1 / 0;
- }, CUSTOM_THREAD_POOL)
- .exceptionally(e -> {
- log.error("异步运行异常信息: " + e.getMessage(), e);
- throw new BusinessException(e.getMessage());
- });
- } catch (Exception e) {
- log.error("异常信息: " + e.getMessage(), e);
- throw new BusinessException(e.getMessage());
- }
结果:接口返回成功,控制台打印异步线程异常日志,主线程没有打印异常日志
- // whenComplete获取异常信息: 异常是存在于异步当中的, 不能被主线程捕获
- try {
- CompletableFuture.runAsync(() -> {
- int i = 1 / 0;
- }, CUSTOM_THREAD_POOL)
- .whenComplete((r, e) -> {
- if (e != null) {
- log.error("异步执行异常信息: " + e.getMessage(), e);
- throw new BusinessException(e.getMessage());
- }
- });
- } catch (Exception e) {
- log.error("异常信息: " + e.getMessage(), e);
- throw new BusinessException(e.getMessage());
- }
结果:结果返回成功,控制台打印异步线程异常信息,主线程没有打印异常信息。另外,搜索公众号Linux就该这样学后台回复“猴子”,获取一份惊喜礼包。
- // handle获取异常信息: 异常是存在于异步当中的, 不能被主线程捕获
- try {
- CompletableFuture.runAsync(() -> {
- int i = 1 / 0;
- }, CUSTOM_THREAD_POOL)
- .handle((r, e) -> {
- if (e != null) {
- log.error("异步执行异常信息: " + e.getMessage(), e);
- throw new BusinessException(e.getMessage());
- }
- return null;
- });
- } catch (Exception e) {
- log.error("异常信息: " + e.getMessage(), e);
- throw new BusinessException(e.getMessage());
- }

结果:结果返回成功,控制台打印异步线程异常信息,主线程没有打印异常信息
- try {
- CompletableFuture.runAsync(() -> {
- int i = 1 / 0;
- }, CUSTOM_THREAD_POOL)
- .exceptionally(e -> {
- log.error("异步执行异常信息: " + e.getMessage(), e);
- throw new BusinessException(e.getMessage());
- }).join();
- } catch (Exception e) {
- log.error("异常信息: " + e.getMessage(), e);
- throw new BusinessException(e.getMessage());
- }
-
- try {
- CompletableFuture.runAsync(() -> {
- int i = 1 / 0;
- }, CUSTOM_THREAD_POOL)
- .exceptionally(e -> {
- log.error("异步执行异常信息: " + e.getMessage(), e);
- throw new BusinessException(e.getMessage());
- }).get(2, TimeUnit.SECONDS);
- } catch (Exception e) {
- log.error("异常信息: " + e.getMessage(), e);
- throw new BusinessException(e.getMessage());
- }

直接的异步方法后调用get()/join()。
在使用异步CompletableFuture时,无论是否有返回值都要调用get()/join()方法,避免程序执行报错了,仍然返回成功。如果在程序报错时需要对上一个异步任务结果做其他操作,可以调用whenComplete()
、handle()
处理,如果只是对异常做处理,不涉及对上一个异步任务结果的情况,调用exceptionally()
处理。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。