将Java未来转化为CompletableFuture
Java 8引入了CompletableFuture
,这是一个可组合的Future的新实现(包括一堆thenXxx方法)。 我想独占地使用它,但是我想使用的许多库只返回不可组合的Future
实例。
有一种方法来包装在一个CompleteableFuture
里面的一个返回的Future
实例,这样我就可以编写它了吗?
有一种方法,但你不会喜欢它。 下面的方法将Future<T>
转换为CompletableFuture<T>
:
public static <T> CompletableFuture<T> makeCompletableFuture(Future<T> future) { return CompletableFuture.supplyAsync(() -> { try { return future.get(); } catch (InterruptedException|ExecutionException e) { throw new RuntimeException(e); } }); }
显然,这种方法的问题是,对于每一个未来 ,一个线程将被阻塞,等待未来的结果 – 与期货的想法相冲突。 在某些情况下,可能会做得更好。 但总的来说,如果不积极等待未来的结果,就没有解决办法。
如果您想要使用的库还提供了Future风格以外的callback风格方法,则可以为其提供一个处理程序,以便在不添加任何线程阻塞的情况下完成CompletableFuture。 像这样:
AsynchronousFileChannel open = AsynchronousFileChannel.open(Paths.get("/some/file")); // ... CompletableFuture<ByteBuffer> completableFuture = new CompletableFuture<ByteBuffer>(); open.read(buffer, position, null, new CompletionHandler<Integer, Void>() { @Override public void completed(Integer result, Void attachment) { completableFuture.complete(buffer); } @Override public void failed(Throwable exc, Void attachment) { completableFuture.completeExceptionally(exc); } }); completableFuture.thenApply(...)
没有callback,我看到解决这个问题的唯一方法就是使用一个轮询循环,将所有的Future.isDone()
检查放在一个线程中,然后在Future可以运行时调用完成。
我发表了一个小小的未来计划,试图在答案中比直接的方式做得更好。
主要思想是使用唯一的一个线程(当然不仅仅是一个旋转循环)来检查里面的所有期货状态,这有助于避免每个Future – > CompletableFuture变换阻塞一个线程池。
用法示例:
Future oldFuture = ...; CompletableFuture profit = Futurity.shift(oldFuture);
让我build议另一个(希望,更好)选项: https : //github.com/vsilaev/java-async-await/tree/master/com.farata.lang.async.examples/src/main/java/com/farata /同时
简而言之,这个想法如下:
- 介绍
CompletableTask<V>
接口 –CompletionStage<V>
+RunnableFuture<V>
- Warp
ExecutorService
从submit(...)
方法返回CompletableTask
(而不是Future<V>
) - 做完了,我们有可运行和可组合的期货。
实现使用另一种CompletionStage实现(注意, CompletionStage而不是CompletableFuture):
用法:
J8ExecutorService exec = J8Executors.newCachedThreadPool(); CompletionStage<String> = exec .submit( someCallableA ) .thenCombineAsync( exec.submit(someCallableB), (a, b) -> a + " " + b) .thenCombine( exec.submit(someCallableC), (ab, b) -> ab + " " + c);