我有一个Guava ListenableFuture
实例列表和Spring DeferredResult
列表。我想在列表中为第一个成功的未来设置结果,或者如果超时尚未到期,则从所有期货中获得成功结果。这是我的尝试:
DeferredResult<String> foo() {
DeferredResult<String> result = new DeferredResult<>(3000L);
List<String> resps = newArrayList();
List<ListenableFuture<String>> fList = ...
fList.forEach(f -> Futures.addCallback(f, new FutureCallback<String>() {
@Override
public void onSuccess(String resp) {
resps.add(resp);
}
@Override
public void onFailure(Throwable t) {
// NOP
}
}));
ListenableFuture<List<String>> f0 = Futures.successfulAsList(fList);
Futures.addCallback(f0, new FutureCallback<List<String>>() {
@Override
public void onSuccess(List<String> r) {
if (!result.hasResult()) {
result.
if (r != null) {
result.setResult(...);
}
}
}
@Override
public void onFailure(Throwable t) {
// NOP
}
});
return result;
}
我的代码不起作用,因为它等待所有期货的结果,但我需要关于DeferredResult超时的最快结果。我该如何解决?
答案 0 :(得分:0)
DeferredResult<String> foo() {
DeferredResult<String> result = new DeferredResult<>(3000L);
List<ListenableFuture<String>> fList = ...
ExecutorService serializingExecutor = Executors.newSingleThreadExecutor();
fList.forEach(
f ->
Futures.addCallback(
f,
new FutureCallback<String>() {
@Override
public void onSuccess(String value) {
if (!result.hasResult()) {
result.setResult(value);
}
}
@Override
public void onFailure(Throwable throwable) {}
},
// To avoid race in the callback:
serializingExecutor));
return result;
}
答案 1 :(得分:0)
这会返回包装器对象,其中包含在超时之前设法完成的Futures的结果列表,并指示是否所有已完成(allFinished
属性)。
在您的处理代码中,您可以检查是否全部完成,并返回整个列表或仅返回第一个项目(如果没有未完成,则返回任何内容)。
DeferredResult<ResultWrapper> foo() {
DeferredResult<ResultWrapper> result = new DeferredResult<>(3000L);
ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(3));
List<ListenableFuture<String>> fList = IntStream.range(1, 1000)
.mapToObj(i -> executor.submit(() -> String.valueOf(i))).collect(Collectors.toList());
List<String> resps = Lists.newArrayListWithCapacity(fList.size());
Object lock = new Object();
fList.forEach(f -> Futures.addCallback(f, new FutureCallback<String>() {
@Override
public void onSuccess(String resp) {
synchronized (lock) {
resps.add(resp);
result.setResult(new ResultWrapper(
resps.size() == fList.size(),
ImmutableList.copyOf(resps)));
}
}
@Override
public void onFailure(Throwable t) {
// NOP
}
}));
return result;
}
private static class ResultWrapper {
private boolean allFinished;
private List<String> list;
public ResultWrapper(boolean allFinished, List<String> list) {
this.allFinished = allFinished;
this.list = list;
}
public boolean isAllFinished() {
return allFinished;
}
public List<String> getList() {
return list;
}
}