Transforme el futuro de Java en un futuro completable

Java 8 presenta CompletableFuture , una nueva implementación de Future que se puede componer (incluye un grupo de métodos thenXxx). Me gustaría utilizar esto de manera exclusiva, pero muchas de las bibliotecas que deseo utilizar solo devuelven instancias Future no compibles.

¿Hay alguna manera de concluir las instancias Future devueltas dentro de un CompleteableFuture para que pueda componerlo?

Hay una manera, pero no te gustará. El siguiente método transforma un Future en un CompletableFuture :

 public static  CompletableFuture makeCompletableFuture(Future future) { return CompletableFuture.supplyAsync(() -> { try { return future.get(); } catch (InterruptedException|ExecutionException e) { throw new RuntimeException(e); } }); } 

Obviamente, el problema con este enfoque es que, para cada futuro , un hilo se bloqueará para esperar el resultado del futuro, lo que contradice la idea de futuro. En algunos casos, podría ser posible hacerlo mejor. Sin embargo, en general, no hay solución sin esperar activamente el resultado del futuro .

Si la biblioteca que desea utilizar también ofrece un método de estilo de callback además del estilo Futuro, puede proporcionarle un controlador que complete el CompletableFuture sin ningún locking adicional de subprocesos. Al igual que:

  AsynchronousFileChannel open = AsynchronousFileChannel.open(Paths.get("/some/file")); // ... CompletableFuture completableFuture = new CompletableFuture(); open.read(buffer, position, null, new CompletionHandler() { @Override public void completed(Integer result, Void attachment) { completableFuture.complete(buffer); } @Override public void failed(Throwable exc, Void attachment) { completableFuture.completeExceptionally(exc); } }); completableFuture.thenApply(...) 

Sin la callback, la única otra forma en que veo resolver esto es usar un ciclo de sondeo que coloca todas las comprobaciones de Future.isDone() en un solo hilo y luego invocando completar cada vez que se puede obtener un futuro.

Publiqué un pequeño proyecto de futuro que trata de hacer una mejor manera que la respuesta directa .

La idea principal es utilizar el único hilo (y, por supuesto, no solo un ciclo de giro) para verificar todos los estados futuros en el interior, lo que ayuda a evitar el locking de un hilo de un grupo para cada transformación Future -> CompletableFuture.

Ejemplo de uso:

 Future oldFuture = ...; CompletableFuture profit = Futurity.shift(oldFuture); 

Permítanme sugerir otra opción (con suerte, mejor): https://github.com/vsilaev/java-async-await/tree/master/com.farata.lang.async.examples/src/main/java/com/farata /concurrente

En resumen, la idea es la siguiente:

  1. Introduzca la interfaz CompletableTask : la unión de CompletionStage + RunnableFuture
  2. Warp ExecutorService para devolver CompletableTask de los métodos de submit(...) (en lugar de Future )
  3. Hecho, tenemos futuros convertibles Y compostables.

La implementación utiliza una implementación alternativa de CompletionStage (preste atención, CompletionStage en lugar de CompletableFuture):

Uso:

 J8ExecutorService exec = J8Executors.newCachedThreadPool(); CompletionStage = exec .submit( someCallableA ) .thenCombineAsync( exec.submit(someCallableB), (a, b) -> a + " " + b) .thenCombine( exec.submit(someCallableC), (ab, b) -> ab + " " + c); 

Sugerencia:

http://www.thedevpiece.com/converting-old-java-future-to-completablefuture/

Pero, básicamente:

 public class CompletablePromiseContext { private static final ScheduledExecutorService SERVICE = Executors.newSingleThreadScheduledExecutor(); public static void schedule(Runnable r) { SERVICE.schedule(r, 1, TimeUnit.MILLISECONDS); } } 

Y, el Promesa Completable:

 public class CompletablePromise extends CompletableFuture { private Future future; public CompletablePromise(Future future) { this.future = future; CompletablePromiseContext.schedule(this::tryToComplete); } private void tryToComplete() { if (future.isDone()) { try { complete(future.get()); } catch (InterruptedException e) { completeExceptionally(e); } catch (ExecutionException e) { completeExceptionally(e.getCause()); } return; } if (future.isCancelled()) { cancel(true); return; } CompletablePromiseContext.schedule(this::tryToComplete); } } 

Ejemplo:

 public class Main { public static void main(String[] args) { final ExecutorService service = Executors.newSingleThreadExecutor(); final Future stringFuture = service.submit(() -> "success"); final CompletableFuture completableFuture = new CompletablePromise<>(stringFuture); completableFuture.whenComplete((result, failure) -> { System.out.println(result); }); } } 
    Intereting Posts