175 votes

Comment appeler une méthode de manière asynchrone en Java ?

J'ai examiné Les goroutines de Go et j'ai pensé qu'il serait intéressant d'avoir quelque chose de similaire en Java. D'après mes recherches, la façon la plus courante de paralléliser un appel de méthode est de faire quelque chose comme :

final String x = "somethingelse";
new Thread(new Runnable() {
           public void run() {
                x.matches("something");             
    }
}).start();

Ce n'est pas très élégant. Existe-t-il une meilleure façon de procéder ? J'avais besoin d'une telle solution dans un projet et j'ai donc décidé d'implémenter ma propre classe enveloppante autour d'un appel de méthode asynchrone.

J'ai publié ma classe enveloppante dans J-Go . Mais je ne sais pas si c'est une bonne solution. L'utilisation est simple :

SampleClass obj = ...
FutureResult<Integer> res = ...
Go go = new Go(obj);
go.callLater(res, "intReturningMethod", 10);         //10 is a Integer method parameter
//... Do something else
//...
System.out.println("Result: "+res.get());           //Blocks until intReturningMethod returns

ou moins verbeux :

Go.with(obj).callLater("myRandomMethod");
//... Go away
if (Go.lastResult().isReady())                //Blocks until myRandomMethod has ended
    System.out.println("Method is finished!");

En interne, j'utilise une classe qui implémente Runnable et j'effectue un travail de Reflection pour obtenir l'objet de la méthode correcte et l'invoquer.

J'aimerais avoir un avis sur ma petite bibliothèque et sur le fait de faire des appels de méthodes asynchrones comme celui-ci en Java. Est-ce sûr ? Existe-t-il déjà un moyen plus simple ?

1voto

FlameBlazer Points 1384

Ce n'est pas vraiment lié, mais si je devais appeler une méthode de manière asynchrone, par exemple matches(), j'utiliserais :

private final static ExecutorService service = Executors.newFixedThreadPool(10);
public static Future<Boolean> matches(final String x, final String y) {
    return service.submit(new Callable<Boolean>() {

        @Override
        public Boolean call() throws Exception {
            return x.matches(y);
        }

    });
}

Ensuite, pour appeler la méthode asynchrone, j'utiliserais :

String x = "somethingelse";
try {
    System.out.println("Matches: "+matches(x, "something").get());
} catch (InterruptedException e) {
    e.printStackTrace();
} catch (ExecutionException e) {
    e.printStackTrace();
}

J'ai testé cela et cela fonctionne. J'ai juste pensé que cela pourrait aider d'autres personnes si elles venaient juste pour la "méthode asynchrone".

1voto

vitro Points 375

Il existe également une bibliothèque intéressante pour Async-Await créée par EA : https://github.com/electronicarts/ea-async

Extrait de leur Readme :

Avec EA Async

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);
    }
}

Sans EA Async

import static java.util.concurrent.CompletableFuture.completedFuture;

public class Store
{
    public CompletableFuture<Boolean> buyItem(String itemTypeId, int cost)
    {
        return bank.decrement(cost)
            .thenCompose(result -> {
                if(!result) {
                    return completedFuture(false);
                }
                return inventory.giveItem(itemTypeId).thenApply(res -> 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