检测 CompletableFuture 链中的超时

Detect timeouts in a CompletableFuture chain

是否有任何可能的安全方法来检测 CompletableFuture 链中的超时?

O someValue = CompletableFuture.supplyAsync(() -> {
                ...
                // API Call
                ...
            }).thenApply(o -> {
                ...
            }).thenApply(o -> {
                // If the chain has timed out, I still have 'o' ready here
                // So at least cache it here, so it's available for the next request
                // Even though the current request will return with a 'null'
                ...
            }).get(10, TimeUnit.SECONDS);
// cache 'someValue'
return someValue;

它在没有超时的情况下成功完成,我可以使用 'someValue' 并用它做任何事情

如果超时,它会抛出 TimeoutException 并且我已经丢失了值,即使它仍在后台处理

我的想法是,即使它超时并且由于线程中的 API 调用仍然在后台完成并且 returns 响应,我可以使用该值,比方说,缓存

至少在你展示的方式上不是。当抛出异常时,您将失去获得 API 调用结果的任何机会,即使它已完成。您在这样的链中缓存的唯一机会如下所示,这无助于超时 API 调用自身

.thenApplyAsync(o -> {
    cache = o;
    // do something
}).thenApplyAsync(o -> {
    cache = o;
    // do something more
}).get(10, TimeUnit.SECONDS);

然而通读 this 给了我一个想法,如果你做了类似下面的事情会怎样

SynchronousQueue<Result> q = new SynchronousQueue<>();
CompletableFuture.supplyAsync(() -> {
    // API call
}.thenAccept(result -> {
    cache.put(result);   // cache the value
    q.offer(result); // offer value to main thread, if still there
}
);

// Main thread waits 10 seconds for a value to be asynchronously offered into the queue
// In case of timeout, null is returned, but any operations done
// before q.offer(result) are still performed

return queue.poll(10, TimeUnit.SECONDS);

在 10 秒内未完成的 API 调用仍被处理到缓存中,因为它是异步接受的并且超时发生在主线程而不是 CompletableFuture 链中,即使原始请求不会得到结果(我想必须优雅地处理它)。