我要列出我想等待的可完成期货。使用以下代码。
public static <T> CompletableFuture<List<T>> finishAllQuery(
List<CompletableFuture<T>> futures) {
CompletableFuture<Void> allDoneFuture =
CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()]));
return allDoneFuture.thenApply(
v -> futures.stream().filter(Objects::nonNull)
.map(future -> future.join())
.collect(Collectors.toList())
);
}
CompletableFuture<List<Result>> allResponse = finishAllQuery(futures);
allResponse.get(5, milliseconds)
问题是,在所有期货中,其中一些期货可能会变慢,我希望到期后,get方法返回所有已完成的结果。有办法吗?
非常感谢。
答案 0 :(得分:0)
如果您不一定要完成所有期货交易,则不应使用allOf()
。您可以改为使用CompletionService,然后将poll()方法与超时一起使用。因此,流程将是:
elapsedTime = 0; availableTime = 5ms; completedFutures = List();
while (elapsedTime < availableTime):
remainingTime = availableTime - elapsedTime;
startTime = currentTime();
completedFutures.add(CompletionService.poll(timeout=remainingTime));
elapsedTime += (currentTime() - startTime)
答案 1 :(得分:0)
这应该由finishAllQuery
本身来处理。例如,从Java 9开始,您可以使用
public static <T> CompletableFuture<List<T>> finishAllQuery(
List<CompletableFuture<T>> futures, long timeOut, TimeUnit unit) {
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
.completeOnTimeout(null, timeOut, unit)
.thenApply(v -> futures.stream()
.filter(CompletableFuture::isDone)
.map(CompletableFuture::join)
.collect(Collectors.toList()));
}
使用completeOnTimeout
,我们可以在超时后用预定义的值强制完成将来。在这里,我们仅使用null
,因为allOf
的结果值无关紧要。
我们只需要添加一个过滤条件,即可跳过所有尚未完成的期货,否则,join
将阻塞线程。
这可以像
一样使用CompletableFuture<List<Result>> allResponse
= finishAllQuery(futures, 5, TimeUnit.MILLISECONDS);
List<Result> list = allResponse.join(); // will wait at most 5 milliseconds
对于Java 8,我们可以使用
static <T> CompletableFuture<T> completeOnTimeout(
CompletableFuture<T> cf, T value, long timeOut, TimeUnit unit) {
ScheduledExecutorService e = Executors.newSingleThreadScheduledExecutor();
ScheduledFuture<Boolean> job = e.schedule(() -> cf.complete(value), timeOut, unit);
return cf.whenComplete((x,y) -> { job.cancel(false); e.shutdown(); });
}
缺少的功能,需要进行少量重写:
public static <T> CompletableFuture<List<T>> finishAllQuery(
List<CompletableFuture<T>> futures, long timeOut, TimeUnit unit) {
return completeOnTimeout(
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])),
null, timeOut, unit)
.thenApply(v -> futures.stream()
.filter(CompletableFuture::isDone)
.map(CompletableFuture::join)
.collect(Collectors.toList()));
}
调用方使用方法的方式不变。
对于生产用途,值得重写completeOnTimeout
方法以重用ScheduledExecutorService
,但这还需要添加关闭代码或创建守护程序线程的线程工厂。使用Java 9或更高版本,您可以免费获得。