我正在解决一个List<ListenableFuture<T>>
问题。我想将所有这些期货的结果汇总到一个超时的List<T>
中。天真的方法是这样的:
List<T> blockForResponses(List<ListenableFuture<T>> futures, long timeoutMillis) {
return futures.stream()
.map(future -> future.get(timeoutMillis,TimeUnit.MILLISECONDS)
.collect(Collectors.toList());
}
这是行不通的,因为它等待每个将来的超时,我希望它是整个列表的超时。手动跟踪经过了多少时间也是行不通的,因为如果第一个超时了,就没有时间再尝试其他时间了。
我正在寻找的解决方案将对所有期货强制执行超时,并在超时时间过去或列表中的所有期货均已完成时返回。然后,我可以自己检查列表中的每个将来,以汇总结果并检查哪些超时。
答案 0 :(得分:2)
这个问题比我想象的要简单。我能够使用Futures.allAsList
方法,然后捕获TimeoutException
:
List<T> blockForResponses(List<ListenableFuture<T>> futures, long timeoutMillis) {
ListenableFuture<List<T>> futureOfList = Futures.allAsList(futures);
List<T> responses;
try {
responses = futureOfList.get(timeoutMillis, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
responses = new ArrayList<>();
for (ListenableFuture<T> future : futures) {
if (future.isDone()) {
responses.add(Uninterruptibles.getUninterruptibly(future));
}
}
}
return responses;
}
答案 1 :(得分:0)
所以我摆弄了一下(直到今天晚上才使用Guava的Listenable界面),但我认为这可能对您有用: 基本包装;
import static com.google.common.util.concurrent.Futures.catching;
import static com.google.common.util.concurrent.Futures.successfulAsList;
import static com.google.common.util.concurrent.Futures.withTimeout;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningScheduledExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
public class FuturesExample {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ListeningScheduledExecutorService scheduledExecutorService = MoreExecutors
.listeningDecorator(Executors.newScheduledThreadPool(20));
List<ListenableFuture<Integer>> list = new LinkedList<>();
for (int i = 1; i <= 4; i++) {
list.add(catching(
withTimeout(scheduledExecutorService.submit(getCallback(i * 1000, i)), 3, TimeUnit.SECONDS,
scheduledExecutorService),
TimeoutException.class, exception -> 0, scheduledExecutorService));
}
ListenableFuture<List<Integer>> result = successfulAsList(list);
Optional<Integer> sum = result.get().stream().reduce(Integer::sum);
System.out.println(sum.orElse(-1));
scheduledExecutorService.shutdownNow();
}
private static Callable<Integer> getCallback(int timeout, int value) {
return () -> {
Thread.sleep(timeout);
return value;
};
}
}
编辑:对期货使用静态导入时,代码会更干净