如何处理 CompletableFuture get() 方法的异常
How to handle exception of CompletableFuture get() method
我需要向第 3 方网址发送请求,所以我在 getStatus()
方法上使用了 @Async
,其中 enum
的 returns CompletableFuture
并且如果 TimeoutException
被抛出我想考虑状态为 DOWN 或如何捕获每个调用的 InterruptedException
和 ExecutionException
try {
firstAppStatus = service1.getStatus().get(20, TimeUnit.SECONDS);
} catch (TimeoutException e) {
firstAppStatus = ComponentStatusEnum.DOWN;
}
try {
secondAppStatus = service2.getStatus().get(20, TimeUnit.SECONDS);
} catch (TimeoutException e) {
secondAppStatus = ComponentStatusEnum.DOWN;
}
try {
thirdAppStatus = service3.getStatus().get(20, TimeUnit.SECONDS);
} catch (TimeoutException e) {
thirdAppStatus = ComponentStatusEnum.DOWN;
}
我知道此代码将按顺序执行,所以 运行 它们如何与此行为异步而不对客户端请求超时进行更改
使用 Java 9 你可以使用 completeOnTimeout
:
CompletableFuture<ComponentStatusEnum> firstAppStatus = service1.getStatus().completeOnTimeout(ComponentStatusEnum.DOWN, 20, TimeUnit.SECONDS);
更多信息here。
如果我没理解错的话,你想要这样的东西:
// allow all three requests to run concurrently
CompletableFuture<ComponentStatusEnum> status1 = service1.getStatus();
CompletableFuture<ComponentStatusEnum> status2 = service2.getStatus();
CompletableFuture<ComponentStatusEnum> status3 = service3.getStatus();
// wait for either, the completion of all three or the timeout, whatever comes first
try {
CompletableFuture.allOf(status1, status2, status3).get(20, TimeUnit.SECONDS);
} catch(TimeoutException|InterruptedException|ExecutionException ex) {
// no action, as all cases are handled below
}
// get results with fall-backs on timeout
firstAppStatus = status1.getNow(ComponentStatusEnum.DOWN);
secondAppStatus = status2.getNow(ComponentStatusEnum.DOWN);
thirdAppStatus = status3.getNow(ComponentStatusEnum.DOWN);
首先,如果要让所有请求运行并行,不要立即查询结果。然后,使用allOf
,您可以等待所有操作的完成与单个超时。
getNow
是在可用时立即获取结果的正确操作,如果操作尚未完成,则为指定的回退值。原则上,操作可能会在获取 TimeoutException
和调用 getNow
之间的短暂 window 时间内完成,但这不会对您的应用程序逻辑造成任何问题。
关于异常处理,getNow
的行为类似于 join()
在基础操作失败时抛出未经检查的 CompletionException
而不是已检查的 ExecutionException
。如果你没有捕捉到它,它会传播给调用者,如果你对这种情况没有特殊处理,这是最好的选择。如果超时等待被打断,它的行为就像你有一个更小的超时一样;操作可能已经完成或在 getNow
.
获得回退值
我需要向第 3 方网址发送请求,所以我在 getStatus()
方法上使用了 @Async
,其中 enum
的 returns CompletableFuture
并且如果 TimeoutException
被抛出我想考虑状态为 DOWN 或如何捕获每个调用的 InterruptedException
和 ExecutionException
try {
firstAppStatus = service1.getStatus().get(20, TimeUnit.SECONDS);
} catch (TimeoutException e) {
firstAppStatus = ComponentStatusEnum.DOWN;
}
try {
secondAppStatus = service2.getStatus().get(20, TimeUnit.SECONDS);
} catch (TimeoutException e) {
secondAppStatus = ComponentStatusEnum.DOWN;
}
try {
thirdAppStatus = service3.getStatus().get(20, TimeUnit.SECONDS);
} catch (TimeoutException e) {
thirdAppStatus = ComponentStatusEnum.DOWN;
}
我知道此代码将按顺序执行,所以 运行 它们如何与此行为异步而不对客户端请求超时进行更改
使用 Java 9 你可以使用 completeOnTimeout
:
CompletableFuture<ComponentStatusEnum> firstAppStatus = service1.getStatus().completeOnTimeout(ComponentStatusEnum.DOWN, 20, TimeUnit.SECONDS);
更多信息here。
如果我没理解错的话,你想要这样的东西:
// allow all three requests to run concurrently
CompletableFuture<ComponentStatusEnum> status1 = service1.getStatus();
CompletableFuture<ComponentStatusEnum> status2 = service2.getStatus();
CompletableFuture<ComponentStatusEnum> status3 = service3.getStatus();
// wait for either, the completion of all three or the timeout, whatever comes first
try {
CompletableFuture.allOf(status1, status2, status3).get(20, TimeUnit.SECONDS);
} catch(TimeoutException|InterruptedException|ExecutionException ex) {
// no action, as all cases are handled below
}
// get results with fall-backs on timeout
firstAppStatus = status1.getNow(ComponentStatusEnum.DOWN);
secondAppStatus = status2.getNow(ComponentStatusEnum.DOWN);
thirdAppStatus = status3.getNow(ComponentStatusEnum.DOWN);
首先,如果要让所有请求运行并行,不要立即查询结果。然后,使用allOf
,您可以等待所有操作的完成与单个超时。
getNow
是在可用时立即获取结果的正确操作,如果操作尚未完成,则为指定的回退值。原则上,操作可能会在获取 TimeoutException
和调用 getNow
之间的短暂 window 时间内完成,但这不会对您的应用程序逻辑造成任何问题。
关于异常处理,getNow
的行为类似于 join()
在基础操作失败时抛出未经检查的 CompletionException
而不是已检查的 ExecutionException
。如果你没有捕捉到它,它会传播给调用者,如果你对这种情况没有特殊处理,这是最好的选择。如果超时等待被打断,它的行为就像你有一个更小的超时一样;操作可能已经完成或在 getNow
.