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 ?

14voto

yegor256 Points 21737

Vous pouvez utiliser @Async de l'annotation jcabi-aspects et AspectJ :

public class Foo {
  @Async
  public void save() {
    // to be executed in the background
  }
}

Lorsque vous appelez save() un nouveau thread démarre et exécute son corps. Votre fil d'exécution principal continue sans attendre le résultat de la fonction save() .

9voto

Anand Points 99

Java propose également une manière intéressante d'appeler des méthodes asynchrones. en java.util.concurrent nous avons ExecutorService qui permet de faire la même chose. Initialisez votre objet comme ceci -

 private ExecutorService asyncExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

puis appeler la fonction comme-

asyncExecutor.execute(() -> {

                        TimeUnit.SECONDS.sleep(3L);}

8voto

user3177227 Points 147

Vous pouvez utiliser Future-AsyncResult pour cela.

@Async
public Future<Page> findPage(String page) throws InterruptedException {
    System.out.println("Looking up " + page);
    Page results = restTemplate.getForObject("http://graph.facebook.com/" + page, Page.class);
    Thread.sleep(1000L);
    return new AsyncResult<Page>(results);
}

Référence : https://spring.io/guides/gs/async-method/

3voto

yegor256 Points 21737

Vous pouvez utiliser AsyncFunc de Cactus :

boolean matches = new AsyncFunc(
  x -> x.matches("something")
).apply("The text").get();

Elle sera exécutée en arrière-plan et le résultat sera disponible dans la rubrique get() en tant que Future .

2voto

user59600 Points 101

Ce n'est probablement pas une vraie solution, mais maintenant - en Java 8 - vous pouvez faire en sorte que ce code soit au moins un peu meilleur en utilisant l'expression lambda.

final String x = "somethingelse";
new Thread(() -> {
        x.matches("something");             
    }
).start();

Vous pouvez même faire cela en une seule ligne, tout en conservant une bonne lisibilité.

new Thread(() -> x.matches("something")).start();

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