如何使用 FallbackFuture 来处理 TimeoutException?
How to use FallbackFuture to handle TimeoutException?
我有我的任务和后备方案:
ListenableFuture<T> listenableAsyncTask = executorService.submit(asyncTaskCallable);
ListenableFuture<T> listenableFallbackTask = executorService.submit(fallBackTaskCallable);
从他们那里,我形成了一个容错的ListenableFuture:
ListenableFuture<T> failTolerantListenableFuture = Futures.withFallback(listenableAsyncTask, new FutureFallback<T>() {
@Override
public ListenableFuture<T> create(Throwable t) throws Exception {
return listenableFallbackTask;
}
});
我有一个容错期货列表:
List<ListenableFuture<T>> listenableFutures = ...;
是时候出结果了,在一定的时间内:
result = Futures.allAsList(listenableFutures).get(50,TimeUnit.MILLISECONDS);
此时,我预计如果任务未能在 50 毫秒内完成,return 输出将由轻量级的 fallBackTask 处理。
但与我计划的不同,我遇到了以下异常:
java.util.concurrent.TimeoutException: Timeout waiting for task.
这导致我丢失了其他成功任务的所有结果。在这种情况下,回退似乎对我不起作用。或者我误解了这个概念?
我们需要区分"the Future
fails"和"the call to Future.get
fails."
- "The
Future
fails"如果你提交的任务抛出异常。 (出于 withFallback
的目的,我们也将取消视为失败。但这与此无关,并且行为可能有一天会改变。)
- "The call to
Future.get
fails" 如果 任何 发生以下情况:
Future
失败
- 通话超时
- 通话中断
withFallback
只处理Future
失败的情况,不处理超时或中断的情况。
如果你的目标是检索所有在 50 毫秒内完成的主要结果,所有其他情况回落到次要结果,你可以尝试这样的事情,它使用 withTimeout
自动失败给定超时后的 Future
:
List<ListenableFuture<T>> originalFutures = ...;
List<ListenableFuture<T>> defaultAfterTimeoutFutures = new ArrayList<>();
for (ListenableFuture<T> f : originalFutures) {
f = Futures.withTimeout(f, 50, MILLISECONDS, executor);
f = Futures.withFallback(f, ...);
defaultAfterTimeoutFutures.add(f);
}
result = Futures.allAsList(defaultAfterTimeoutFutures).get();
但请注意,最后一个 get
调用可能会等待超过 50 毫秒:如果主 Future
失败,则 get
调用必须等到其回退完成。如果您不想等待回退,那么您还需要用 withTimeout
将它们包装起来。如果你确实包装它们,那么它们将在超时后失败,此时 allAsList
也会失败。如果你不想要那个,那么你需要使用 successfulAsList
(而不是 allAsList
)或者再次用 withFallback
包装包装器,这次的值总是立即可用。
我有我的任务和后备方案:
ListenableFuture<T> listenableAsyncTask = executorService.submit(asyncTaskCallable);
ListenableFuture<T> listenableFallbackTask = executorService.submit(fallBackTaskCallable);
从他们那里,我形成了一个容错的ListenableFuture:
ListenableFuture<T> failTolerantListenableFuture = Futures.withFallback(listenableAsyncTask, new FutureFallback<T>() {
@Override
public ListenableFuture<T> create(Throwable t) throws Exception {
return listenableFallbackTask;
}
});
我有一个容错期货列表:
List<ListenableFuture<T>> listenableFutures = ...;
是时候出结果了,在一定的时间内:
result = Futures.allAsList(listenableFutures).get(50,TimeUnit.MILLISECONDS);
此时,我预计如果任务未能在 50 毫秒内完成,return 输出将由轻量级的 fallBackTask 处理。
但与我计划的不同,我遇到了以下异常:
java.util.concurrent.TimeoutException: Timeout waiting for task.
这导致我丢失了其他成功任务的所有结果。在这种情况下,回退似乎对我不起作用。或者我误解了这个概念?
我们需要区分"the Future
fails"和"the call to Future.get
fails."
- "The
Future
fails"如果你提交的任务抛出异常。 (出于withFallback
的目的,我们也将取消视为失败。但这与此无关,并且行为可能有一天会改变。) - "The call to
Future.get
fails" 如果 任何 发生以下情况:Future
失败- 通话超时
- 通话中断
withFallback
只处理Future
失败的情况,不处理超时或中断的情况。
如果你的目标是检索所有在 50 毫秒内完成的主要结果,所有其他情况回落到次要结果,你可以尝试这样的事情,它使用 withTimeout
自动失败给定超时后的 Future
:
List<ListenableFuture<T>> originalFutures = ...;
List<ListenableFuture<T>> defaultAfterTimeoutFutures = new ArrayList<>();
for (ListenableFuture<T> f : originalFutures) {
f = Futures.withTimeout(f, 50, MILLISECONDS, executor);
f = Futures.withFallback(f, ...);
defaultAfterTimeoutFutures.add(f);
}
result = Futures.allAsList(defaultAfterTimeoutFutures).get();
但请注意,最后一个 get
调用可能会等待超过 50 毫秒:如果主 Future
失败,则 get
调用必须等到其回退完成。如果您不想等待回退,那么您还需要用 withTimeout
将它们包装起来。如果你确实包装它们,那么它们将在超时后失败,此时 allAsList
也会失败。如果你不想要那个,那么你需要使用 successfulAsList
(而不是 allAsList
)或者再次用 withFallback
包装包装器,这次的值总是立即可用。