Soy un desarrollador normal de C # pero ocasionalmente desarrollo aplicaciones en Java. Me pregunto si hay algún equivalente Java de C # async / await. En palabras simples, ¿cuál es el equivalente de Java de:
async Task<int> AccessTheWebAsync()
{
HttpClient client = new HttpClient();
var urlContents = await client.GetStringAsync("http://msdn.microsoft.com");
return urlContents.Length;
}
async
, sino usar valoresFuture
o en suObservable
lugar.Respuestas:
No, no hay ningún equivalente de async / await en Java, o incluso en C # antes de v5.
Es una característica de lenguaje bastante compleja para construir una máquina de estado detrás de escena.
Hay relativamente poco soporte de lenguaje para asincronía / concurrencia en Java, pero el
java.util.concurrent
paquete contiene muchas clases útiles sobre esto. (No es exactamente equivalente a la Biblioteca paralela de tareas, pero la aproximación más cercana a ella).fuente
El
await
utiliza una continuación para ejecutar código adicional cuando se complete la operación asíncrona (client.GetStringAsync(...)
).Entonces, como la aproximación más cercana, usaría una solución basada en
CompletableFuture<T>
(el equivalente de Java 8 a .netTask<TResult>
) para procesar la solicitud Http de forma asincrónica.ACTUALIZADO el 25-05-2016 a AsyncHttpClient v.2 lanzado el 13 de abril de 2016:
Entonces, el equivalente de Java 8 al ejemplo de OP
AccessTheWebAsync()
es el siguiente:Este uso se tomó de la respuesta a ¿Cómo obtengo un CompletableFuture de una solicitud Async Http Client? y que está de acuerdo con la nueva API proporcionada en la versión 2 de AsyncHttpClient lanzada el 13 de abril de 2016, que ya tiene soporte intrínseco
CompletableFuture<T>
.Respuesta original con la versión 1 de AsyncHttpClient:
Para ello tenemos dos enfoques posibles:
el primero usa IO sin bloqueo y lo llamo
AccessTheWebAsyncNio
. Sin embargo, debido a queAsyncCompletionHandler
es una clase abstracta (en lugar de una interfaz funcional), no podemos pasar una lambda como argumento. Por lo tanto, incurre en verbosidad inevitable debido a la sintaxis de las clases anónimas. Sin embargo, esta solución es la más cercana al flujo de ejecución del ejemplo C # dado .el segundo es un poco menos detallado, sin embargo, presentará una nueva tarea que finalmente bloqueará un hilo
f.get()
hasta que se complete la respuesta.Primer enfoque , más detallado pero sin bloqueo:
Segundo enfoque menos detallado pero bloqueando un hilo:
fuente
Echa un vistazo a ea-async que reescribe el código de bytes de Java para simular async / wait bastante bien. Según su léame: "Está fuertemente inspirado por Async-Await en .NET CLR"
fuente
asíncrono y espera son azúcares sintácticos. La esencia de async y esperar es la máquina de estados. El compilador transformará su código asíncrono / espera en una máquina de estado.
Al mismo tiempo, para que async / wait sea realmente practicable en proyectos reales, necesitamos tener muchas funciones de biblioteca Async I / O ya implementadas. Para C #, la mayoría de las funciones de E / S sincronizadas originales tienen una versión Async alternativa. La razón por la que necesitamos estas funciones asíncronas es porque en la mayoría de los casos, su propio código asíncrono / espera se reducirá a algún método de biblioteca asíncrona.
Las funciones de biblioteca de la versión Async en C # son algo así como el concepto AsynchronousChannel en Java. Por ejemplo, tenemos AsynchronousFileChannel.read que puede devolver un futuro o ejecutar una devolución de llamada después de que se realiza la operación de lectura. Pero no es exactamente lo mismo. Todas las funciones asíncronas de C # devuelven tareas (similar a Future pero más potente que Future).
Entonces, digamos que Java admite async / await, y escribimos un código como este:
Entonces me imagino que el compilador transformará el código asíncrono / espera original en algo como esto:
Y aquí está la implementación de AsyncHandler:
fuente
No existe un equivalente de C # async / await en Java a nivel de lenguaje. Un concepto conocido como Las fibras también conocido como hilos cooperativos también conocido como hilos ligeros podría ser una alternativa interesante. Puede encontrar bibliotecas Java que brinden soporte para fibras.
Bibliotecas Java que implementan Fibras
Puede leer este artículo (de Quasar) para obtener una buena introducción a las fibras. Cubre qué son los subprocesos, cómo se pueden implementar las fibras en la JVM y tiene algún código específico de Quasar.
fuente
Task
clase) al registrar una devolución de llamada.Como se mencionó, no existe un equivalente directo, pero se podría crear una aproximación muy cercana con modificaciones de código de bytes de Java (tanto para instrucciones asíncronas / de espera como para la implementación de continuaciones subyacentes).
Estoy trabajando en este momento en un proyecto que implementa async / await en la parte superior de la biblioteca de continuación JavaFlow , consulte https://github.com/vsilaev/java-async-await
Aún no se ha creado Maven mojo, pero puede ejecutar ejemplos con el agente Java suministrado. Así es como se ve el código asíncrono / espera:
@async es la anotación que marca un método como ejecutable asincrónicamente, await () es una función que espera en CompletableFuture usando continuaciones y una llamada a "return asyncResult (someValue)" es lo que finaliza CompletableFuture / Continuation asociado
Al igual que con C #, el flujo de control se conserva y el manejo de excepciones se puede hacer de manera regular (prueba / captura como en el código ejecutado secuencialmente)
fuente
Java en sí no tiene características equivalentes, pero existen bibliotecas de terceros que ofrecen una funcionalidad similar, por ejemplo, Kilim .
fuente
Primero, comprenda qué es async / await. Es una manera para que una aplicación GUI de subproceso único o un servidor eficiente ejecute múltiples "fibras" o "co-rutinas" o "subprocesos livianos" en un solo subproceso.
Si está de acuerdo con el uso de hilos comunes, entonces el equivalente de Java es
ExecutorService.submit
yFuture.get
. Esto bloqueará hasta que se complete la tarea y devolverá el resultado. Mientras tanto, otros hilos pueden hacer el trabajo.Si desea el beneficio de algo como las fibras, necesita soporte en el contenedor (es decir, en el bucle de eventos GUI o en el controlador de solicitud HTTP del servidor), o escribiendo el suyo.
Por ejemplo, Servlet 3.0 ofrece procesamiento asincrónico. Ofertas de JavaFX
javafx.concurrent.Task
. Sin embargo, estos no tienen la elegancia de las características del lenguaje. Funcionan a través de devoluciones de llamadas ordinarias.fuente
No hay nada nativo de Java que le permita hacer esto como palabras clave asíncronas / aguardadas, pero lo que puede hacer si realmente desea es usar un CountDownLatch . Usted podria entonces imitar asíncrono / Await pasando esto alrededor (al menos en Java7). Esta es una práctica común en las pruebas de unidades de Android donde tenemos que hacer una llamada asíncrona (generalmente una ejecutable publicada por un controlador) y luego esperar el resultado (cuenta atrás).
Sin embargo, usar esto dentro de su aplicación en lugar de su prueba NO es lo que recomiendo. Eso sería extremadamente de mala calidad, ya que CountDownLatch depende de que usted cuente la cantidad correcta de veces y en los lugares correctos.
fuente
Realicé y lancé Java async / await library. https://github.com/stofu1234/kamaitachi
Esta biblioteca no necesita la extensión del compilador, y realiza el procesamiento de IO sin pila en Java.
↓
fuente
Desafortunadamente, Java no tiene equivalente de async / await. Probablemente, lo más cercano que puede obtener es con ListenableFuture from Guava y el encadenamiento del oyente, pero aún sería muy engorroso escribir para casos que involucran múltiples llamadas asincrónicas, ya que el nivel de anidación crecería muy rápidamente.
Si está de acuerdo con usar un idioma diferente además de JVM, afortunadamente hay async / await en Scala, que es un equivalente directo de C # async / await con una sintaxis y semántica casi idénticas: https://github.com/scala/ asíncrono /
Tenga en cuenta que aunque esta funcionalidad necesitaba un soporte de compilador bastante avanzado en C #, en Scala se podía agregar como una biblioteca gracias a un sistema macro muy potente en Scala y, por lo tanto, se puede agregar incluso a versiones anteriores de Scala como 2.10. Además, Scala es compatible con Java, por lo que puede escribir el código asíncrono en Scala y luego llamarlo desde Java.
También hay otro proyecto similar llamado Akka Dataflow http://doc.akka.io/docs/akka/2.3-M1/scala/dataflow.html que usa una redacción diferente pero conceptualmente es muy similar, sin embargo, implementado usando continuaciones delimitadas, no macros (por lo que funciona incluso con versiones anteriores de Scala como 2.9).
fuente
Java no tiene el equivalente directo de la función del lenguaje C # llamada async / await, sin embargo, hay un enfoque diferente del problema que async / await intenta resolver. Se llama proyecto Loom , que proporcionará hilos virtuales para la concurrencia de alto rendimiento. Estará disponible en alguna versión futura de OpenJDK.
Este enfoque también resuelve el " problema de función coloreada " que tiene async / wait
Una característica similar también se puede encontrar en Golang ( goroutines ).
fuente
Si solo busca un código limpio que simule el mismo efecto que async / await en java y no le importa bloquear el hilo que se llama hasta que finalice, como en una prueba, puede usar algo como este código:
fuente
La biblioteca Java AsynHelper incluye un conjunto de clases / métodos de utilidad para tales llamadas asincrónicas (y esperar).
Si se desea ejecutar un conjunto de llamadas a métodos o bloques de código de forma asincrónica, incluye un método auxiliar útil AsyncTask .submitTasks como en el siguiente fragmento.
Si se desea esperar hasta que todos los códigos asíncronos se completen, AsyncTask.submitTasksAndWait se puede usar AsyncTask.submitTasksAndWait.
Además, si se desea obtener un valor de retorno de cada una de las llamadas al método asincrónico o bloque de código, se puede usar AsyncSupplier .submitSuppliers para que el resultado se pueda obtener de la matriz de proveedores de resultados devuelta por el método. A continuación se muestra el fragmento de muestra:
Si el tipo de retorno de cada método difiere, use el siguiente fragmento de fragmento.
El resultado de las llamadas al método asincrónico / bloques de código también se puede obtener en un punto de código diferente en el mismo hilo o en un hilo diferente que en el fragmento de código siguiente.
fuente