Je suis un développeur C # normal mais je développe parfois des applications en Java. Je me demande s'il existe un équivalent Java de C # async / await? En termes simples, quel est l'équivalent java de:
async Task<int> AccessTheWebAsync()
{
HttpClient client = new HttpClient();
var urlContents = await client.GetStringAsync("http://msdn.microsoft.com");
return urlContents.Length;
}
async
, mais à utiliserFuture
ou à laObservable
place.Réponses:
Non, il n'y a pas d'équivalent async / await en Java - ni même en C # avant la v5.
C'est une fonctionnalité de langage assez complexe pour construire une machine à états dans les coulisses.
Il y a relativement peu de prise en charge du langage pour l'asynchronie / concurrence en Java, mais le
java.util.concurrent
package contient beaucoup de classes utiles autour de cela. (Pas tout à fait équivalent à la bibliothèque parallèle de tâches, mais l'approximation la plus proche de celle-ci.)la source
Le
await
utilise une continuation pour exécuter du code supplémentaire lorsque l'opération asynchrone se termine (client.GetStringAsync(...)
).Donc, comme approximation la plus proche, j'utiliserais une solution basée sur
CompletableFuture<T>
(l'équivalent Java 8 de .netTask<TResult>
) pour traiter la requête Http de manière asynchrone.MISE À JOUR le 25-05-2016 vers AsyncHttpClient v.2 publié le 13 avril 2016:
Donc, l'équivalent Java 8 de l'exemple OP de
AccessTheWebAsync()
est le suivant:Cette utilisation a été tirée de la réponse à Comment obtenir un CompletableFuture à partir d'une demande Async Http Client? et qui est selon la nouvelle API fournie dans la version 2 d' AsyncHttpClient publiée le 13 avril 2016, qui a déjà un support intrinsèque pour
CompletableFuture<T>
.Réponse originale utilisant la version 1 d'AsyncHttpClient:
À cette fin, nous avons deux approches possibles:
le premier utilise des E / S non bloquantes et je l'appelle
AccessTheWebAsyncNio
. Pourtant, comme leAsyncCompletionHandler
est une classe abstraite (au lieu d'une interface fonctionnelle), nous ne pouvons pas passer un lambda comme argument. Cela entraîne donc une verbosité inévitable en raison de la syntaxe des classes anonymes. Cependant, cette solution est la plus proche du flux d'exécution de l'exemple C # donné .le second est légèrement moins verbeux mais il soumettra une nouvelle tâche qui finira par bloquer un fil
f.get()
jusqu'à ce que la réponse soit complète.Première approche , plus verbeuse mais non bloquante:
Deuxième approche moins verbeuse mais bloquant un fil:
la source
Découvrez ea-async qui effectue la réécriture de bytecode Java pour simuler async / wait assez bien. Selon leur readme: "Il est fortement inspiré par Async-Await sur le .NET CLR"
la source
async et await sont des sucres syntaxiques. L'essence de l'async et de l'attente est la machine à états. Le compilateur transformera votre code asynchrone / en attente en une machine à états.
Dans le même temps, pour qu'async / await soit vraiment réalisable dans de vrais projets, nous avons besoin de nombreuses fonctions de bibliothèque d'E / S Async déjà en place. Pour C #, la plupart des fonctions d'E / S synchronisées d'origine ont une autre version Async. La raison pour laquelle nous avons besoin de ces fonctions Async est que dans la plupart des cas, votre propre code async / await se résumera à une méthode Async de bibliothèque.
Les fonctions de la bibliothèque de version Async en C # sont un peu comme le concept AsynchronousChannel en Java. Par exemple, nous avons AsynchronousFileChannel.read qui peut renvoyer un Future ou exécuter un rappel une fois l'opération de lecture terminée. Mais ce n'est pas exactement la même chose. Toutes les fonctions C # Async renvoient des tâches (similaires à Future mais plus puissantes que Future).
Alors disons que Java prend en charge async / await, et nous écrivons un code comme celui-ci:
Ensuite, j'imagine que le compilateur transformera le code async / wait original en quelque chose comme ceci:
Et voici l'implémentation pour AsyncHandler:
la source
Il n'y a pas d'équivalent de C # async / await en Java au niveau du langage. Un concept connu sous le nom de Fibres aka threads coopératifs aka threads légers pourrait être une alternative intéressante. Vous pouvez trouver des bibliothèques Java prenant en charge les fibres.
Bibliothèques Java implémentant Fibers
Vous pouvez lire cet article (de Quasar) pour une belle introduction aux fibres. Il couvre ce que sont les threads, comment les fibres peuvent être implémentées sur la JVM et contient du code spécifique à Quasar.
la source
Task
classe) en enregistrant un rappel.Comme il a été mentionné, il n'y a pas d'équivalent direct, mais une approximation très proche pourrait être créée avec des modifications de bytecode Java (pour les instructions de type async / await et l'implémentation des continuations sous-jacentes).
Je travaille actuellement sur un projet qui implémente async / await en plus de la bibliothèque de continuation JavaFlow , veuillez vérifier https://github.com/vsilaev/java-async-await
Aucun mojo Maven n'est encore créé, mais vous pouvez exécuter des exemples avec l'agent Java fourni. Voici à quoi ressemble le code async / await:
@async est l'annotation qui marque une méthode comme exécutable de manière asynchrone, await () est une fonction qui attend sur CompletableFuture en utilisant des continuations et un appel à "return asyncResult (someValue)" est ce qui finalise CompletableFuture / Continuation associé
Comme avec C #, le flux de contrôle est préservé et la gestion des exceptions peut être effectuée de manière régulière (try / catch comme dans le code exécuté séquentiellement)
la source
Java lui-même n'a pas de fonctionnalités équivalentes, mais il existe des bibliothèques tierces qui offrent des fonctionnalités similaires, par exemple Kilim .
la source
Tout d'abord, comprenez ce qu'est async / await. C'est un moyen pour une application GUI à un seul thread ou un serveur efficace d'exécuter plusieurs "fibres" ou "co-routines" ou "threads légers" sur un seul thread.
Si vous êtes d'accord avec l'utilisation de threads ordinaires, l'équivalent Java est
ExecutorService.submit
etFuture.get
. Cela bloquera jusqu'à la fin de la tâche et retournera le résultat. Pendant ce temps, d'autres threads peuvent fonctionner.Si vous voulez bénéficier de quelque chose comme les fibres, vous avez besoin de support dans le conteneur (je veux dire dans la boucle d'événement GUI ou dans le gestionnaire de requêtes HTTP du serveur), ou en écrivant le vôtre.
Par exemple, Servlet 3.0 offre un traitement asynchrone. Offres JavaFX
javafx.concurrent.Task
. Cependant, ceux-ci n'ont pas l'élégance des fonctionnalités du langage. Ils fonctionnent grâce à des rappels ordinaires.la source
Il n'y a rien de natif à Java qui vous permet de faire cela comme les mots-clés async / await, mais ce que vous pouvez faire si vous le souhaitez vraiment, c'est utiliser un CountDownLatch . Vous pouvez alors imiter async / await en le passant (au moins en Java7). C'est une pratique courante dans les tests unitaires Android où nous devons faire un appel asynchrone (généralement un exécutable posté par un gestionnaire), puis attendre le résultat (compte à rebours).
L'utilisation de cela dans votre application, par opposition à votre test, n'est PAS ce que je recommande. Ce serait extrêmement de mauvaise qualité car CountDownLatch dépend de votre compte à rebours le bon nombre de fois et aux bons endroits.
la source
J'ai créé et publié la bibliothèque Java async / await. https://github.com/stofu1234/kamaitachi
Cette bibliothèque n'a pas besoin d'extension de compilateur et réalise un traitement d'E / S sans pile en Java.
↓
la source
Java n'a malheureusement pas d'équivalent async / await. Le plus proche que vous puissiez obtenir est probablement avec ListenableFuture de Guava et le chaînage d'auditeurs, mais il serait toujours très fastidieux d'écrire pour les cas impliquant plusieurs appels asynchrones, car le niveau d'imbrication augmenterait très rapidement.
Si vous êtes d'accord pour utiliser un autre langage en plus de JVM, heureusement, il y a async / await dans Scala qui est un équivalent direct C # async / await avec une syntaxe et une sémantique presque identiques: https://github.com/scala/ asynchrone /
Notez que bien que cette fonctionnalité ait besoin d'un support de compilateur assez avancé en C #, dans Scala, elle pourrait être ajoutée en tant que bibliothèque grâce à un système de macros très puissant dans Scala et peut donc être ajoutée même aux anciennes versions de Scala comme 2.10. De plus, Scala est compatible avec les classes Java, vous pouvez donc écrire le code async dans Scala, puis l'appeler depuis Java.
Il existe également un autre projet similaire appelé Akka Dataflow http://doc.akka.io/docs/akka/2.3-M1/scala/dataflow.html qui utilise un libellé différent mais est conceptuellement très similaire, mais mis en œuvre en utilisant des continuations délimitées, pas des macros (donc cela fonctionne avec les versions Scala encore plus anciennes comme 2.9).
la source
Java n'a pas d'équivalent direct de la fonctionnalité du langage C # appelée async / await, mais il existe une approche différente du problème qu'async / await tente de résoudre. C'est ce qu'on appelle le projet Loom , qui fournira des threads virtuels pour une concurrence à haut débit. Il sera disponible dans une future version d'OpenJDK.
Cette approche résout également le " problème de fonction colorée " qu'async / await a.
Une caractéristique similaire peut également être trouvée à Golang ( goroutines ).
la source
Si vous recherchez juste un code propre qui simule le même effet que async / await en java et que cela ne vous dérange pas de bloquer le thread sur lequel il est appelé jusqu'à ce qu'il soit terminé, comme dans un test, vous pouvez utiliser quelque chose comme ce code:
la source
La bibliothèque Java AsynHelper comprend un ensemble de classes / méthodes utilitaires pour de tels appels asynchrones (et attendre).
Si vous souhaitez exécuter un ensemble d'appels de méthode ou de blocs de code de manière asynchrone, il inclut une méthode d'assistance utile AsyncTask .submitTasks comme dans l'extrait de code ci-dessous.
Si vous souhaitez attendre que tous les codes asynchrones soient exécutés, la variante AsyncTask.submitTasksAndWait peut être utilisée.
De même, si vous souhaitez obtenir une valeur de retour à partir de chaque appel de méthode asynchrone ou bloc de code, AsyncSupplier .submitSuppliers peut être utilisé afin que le résultat puisse être ensuite obtenu à partir du tableau des fournisseurs de résultats renvoyé par la méthode. Voici un exemple d'extrait de code:
Si le type de retour de chaque méthode diffère, utilisez le type d'extrait de code ci-dessous.
Le résultat des appels / blocs de code de méthode asynchrone peut également être obtenu à un point de code différent dans le même thread ou dans un thread différent comme dans l'extrait de code ci-dessous.
la source