222 votes

L'équivalent Java de C# async/await ?

Je suis un développeur C# normal mais il m'arrive de développer 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;
}

11voto

Martin Obrátil Points 48

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 que async/await tente de résoudre. Il s'agit du projet Métier à tisser qui fournira des threads virtuels pour une concurrence à haut débit. Il sera disponible dans une future version d'OpenJDK.

Cette approche permet également de résoudre les problèmes de " problème de fonction colorée " qu'a async/await.

Une fonctionnalité similaire peut également être trouvée dans Golang ( goroutines ).

9voto

Valery Silaev Points 171

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 du bytecode Java (à la fois pour les instructions de type async/await et l'implémentation des continuations sous-jacentes).

Je travaille en ce moment sur un projet qui implémente async/await au dessus de Suite de JavaFlow bibliothèque, veuillez vérifier https://github.com/vsilaev/java-async-await

Aucun mojo Maven n'est encore créé, mais vous pouvez exécuter les exemples avec l'agent Java fourni. Voici à quoi ressemble le code async/await :

public class AsyncAwaitNioFileChannelDemo {

public static void main(final String[] argv) throws Exception {

    ...
    final AsyncAwaitNioFileChannelDemo demo = new AsyncAwaitNioFileChannelDemo();
    final CompletionStage<String> result = demo.processFile("./.project");
    System.out.println("Returned to caller " + LocalTime.now());
    ...
}

public @async CompletionStage<String> processFile(final String fileName) throws IOException {
    final Path path = Paths.get(new File(fileName).toURI());
    try (
            final AsyncFileChannel file = new AsyncFileChannel(
                path, Collections.singleton(StandardOpenOption.READ), null
            );              
            final FileLock lock = await(file.lockAll(true))
        ) {

        System.out.println("In process, shared lock: " + lock);
        final ByteBuffer buffer = ByteBuffer.allocateDirect((int)file.size());

        await( file.read(buffer, 0L) );
        System.out.println("In process, bytes read: " + buffer);
        buffer.rewind();

        final String result = processBytes(buffer);

        return asyncResult(result);

    } catch (final IOException ex) {
        ex.printStackTrace(System.out);
        throw ex;
    }
}

@async est l'annotation qui signale qu'une méthode est exécutable de manière asynchrone, await() est une fonction qui attend un CompletableFuture en utilisant des continuations et un appel à "return asyncResult(someValue)" est ce qui finalise le CompletableFuture/Continuation associé.

Comme en 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 un code exécuté de manière séquentielle).

7voto

Alexei Kaigorodov Points 5841

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 ex. Kilim .

7voto

Aleksandr Dubinsky Points 2488

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 pouvez utiliser des threads ordinaires, l'équivalent Java est le suivant ExecutorService.submit y Future.get . Cela bloquera jusqu'à ce que la tâche soit terminée, et renverra le résultat. Pendant ce temps, d'autres threads peuvent effectuer leur travail.

Si vous voulez bénéficier de quelque chose comme les fibres, vous devez prendre en charge le conteneur (je veux dire dans la boucle d'événements de l'interface graphique ou dans le gestionnaire de requête HTTP du serveur), ou en écrivant le vôtre.

Par exemple, Servlet 3.0 offre un traitement asynchrone. JavaFX offre javafx.concurrent.Task . Ils n'ont cependant pas l'élégance des fonctionnalités du langage. Ils fonctionnent par le biais de callbacks ordinaires.

7voto

walter33 Points 23

Il existe un "équivalent" de l'attente développé par EA : https://github.com/electronicarts/ea-async . Reportez-vous au code d'exemple Java :

import static com.ea.async.Async.await;
import static java.util.concurrent.CompletableFuture.completedFuture;

public class Store
{
    public CompletableFuture<Boolean> buyItem(String itemTypeId, int cost)
    {
        if(!await(bank.decrement(cost))) {
            return completedFuture(false);
        }
        await(inventory.giveItem(itemTypeId));
        return completedFuture(true);
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X