java - await - ExecutorService.submit(Tarea) vs CompletableFuture.supplyAsync(Tarea, Ejecutor)
java 8 promise (3)
Además del tipo de retorno Futuro vs. CompletoFuturo, existen diferencias notables. ¿O cuándo usar qué?
Es bastante simple en realidad. Utiliza el Future
cuando desea que el subproceso en ejecución espere la respuesta de cálculo asíncrono. Un ejemplo de esto es con una combinación / clasificación paralela. Ordene a la izquierda de forma asíncrona, ordene a la derecha de forma síncrona, espere a la izquierda para completar ( future.get()
), future.get()
resultados.
Utiliza un CompleteableFuture
cuando quieres que se ejecute alguna acción, con el resultado una vez completado, de forma asíncrona desde el subproceso ejecutado. Por ejemplo: quiero hacer algunos cálculos de forma asíncrona y cuando calculo, escribo los resultados en algún sistema. Es posible que el subproceso que realiza la solicitud no necesite esperar un resultado.
Puede imitar el ejemplo anterior en un solo ejecutable de Future, pero CompletableFuture
ofrece una interfaz más fluida con un mejor manejo de errores.
Realmente depende de lo que quieras hacer.
¿Y cuáles son las diferencias si utilizo CompletableFutureApi con el Ejecutor predeterminado (el método sin ejecutor)?
Se delegará a ForkJoin.commonPool()
que es un tamaño predeterminado al número de CPU en su sistema. Si está haciendo algo de IO intensivo (lectura y escritura en el sistema de archivos), debe definir el grupo de subprocesos de manera diferente.
Si requiere mucha CPU, usar commonPool tiene más sentido.
Para ejecutar algunas cosas en paralelo o de forma asíncrona, puedo usar un ExecutorService: <T> Future<T> submit(Runnable task, T result);
o la Api CompletableFuture: static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor);
(Supongamos que uso en ambos casos el mismo Ejecutor)
Además del tipo de retorno Future
vs. CompletableFuture
, existen diferencias notables. ¿O cuándo usar qué?
¿Y cuáles son las diferencias si uso la API CompletableFuture
con el Executor
predeterminado (el método sin ejecutor)?
CompletableFuture tiene ricas características como encadenar múltiples futuros, combinar los futuros, ejecutar alguna acción después de que se ejecute el futuro (tanto de forma síncrona como asíncrona), etc.
Sin embargo, CompletableFuture no es diferente de Futuro en términos de rendimiento. Incluso cuando se combinan varias instancias de CompletableFuture (usando .thenCombine y .join al final), ninguna de ellas se ejecuta a menos que llamemos al método .get y durante este tiempo, el subproceso de invocación está bloqueado. Me siento en términos de rendimiento, esto no es mejor que el futuro.
Por favor, avíseme si me estoy perdiendo algún aspecto del rendimiento aquí.
Esto me aclaró la diferencia entre el futuro y el futuro un poco más completo: la diferencia entre el futuro y la promesa
CompletableFuture es más como una promesa.