Comment appeler une méthode avec un thread séparé en Java?


126

disons que j'ai une méthode doWork(). Comment puis-je l'appeler à partir d'un thread séparé (pas le thread principal).


Il se trouve qu'il y a quelques exemples sur cette question connexe récente: tuer une boucle infinie en java
— Greg Hewgill

stackoverflow.com/questions/36832094/ ... J'ai un problème similaire, veuillez m'aider à résoudre ce problème
— Sruthi Acg

Vous pouvez également consulter le blog Java réactif.danlew.net / 2014 / 09 / 15 / grokking-rxjava-part-1 pour les tâches asynchrones
— Nathan Dunn

Réponses:


138

Créez une classe qui implémente l' Runnableinterface. Mettez le code que vous souhaitez exécuter dans la run()méthode - c'est la méthode que vous devez écrire pour vous conformer à l' Runnableinterface. Dans votre thread "principal", créez une nouvelle Threadclasse, en passant au constructeur une instance de votre Runnable, puis appelez start()-la. startindique à la JVM de faire la magie pour créer un nouveau thread, puis d'appeler votre runméthode dans ce nouveau thread.

public class MyRunnable implements Runnable {

    private int var;

    public MyRunnable(int var) {
        this.var = var;
    }

    public void run() {
        // code in the other thread, can reference "var" variable
    }
}

public class MainThreadClass {
    public static void main(String args[]) {
        MyRunnable myRunnable = new MyRunnable(10);
        Thread t = new Thread(myRunnable)
        t.start();
    }    
}

Jetez un œil au didacticiel sur la concurrence de Java pour commencer.

Si votre méthode doit être appelée fréquemment, cela ne vaut peut-être pas la peine de créer un nouveau thread à chaque fois, car il s'agit d'une opération coûteuse. Il serait probablement préférable d'utiliser une sorte de pool de threads. Jetez un oeil à Future, Callable, les Executorclasses dans le java.util.concurrentpaquet.


1
et s'il y a une variable que vous aimeriez passer?
— Louis Rhys

8
La run()méthode ne prend aucun paramètre, vous ne pouvez donc pas y passer de variable. Je suggère que vous le passiez dans le constructeur - je modifierai ma réponse pour le montrer.
— Noel M

1
Existe-t-il un moyen rapide d'appeler une méthode dans un thread différent? Je connais le new Thread() { public void run() {myMethod();}}.start();chemin, est-ce le plus court?
— Steven Roose

@NoelM pouvez-vous expliquer la différence entre la vôtre et la réponse de MANN?
— Asif Mushtaq

2
La réponse de MANN utilise une implémentation anonyme de Runnable- la mienne est une classe qui s'étend Runnable. Et parce que j'ai fait cela, j'ai mon propre constructeur qui transmet l'état à l'objet instancié.
— Noel M

183
Thread t1 = new Thread(new Runnable() {
    @Override
    public void run() {
        // code goes here.
    }
});  
t1.start();

ou

new Thread(new Runnable() {
     @Override
     public void run() {
          // code goes here.
     }
}).start();

ou

new Thread(() -> {
    // code goes here.
}).start();

ou

Executors.newSingleThreadExecutor().execute(new Runnable() {
    @Override
    public void run() {
        myCustomMethod();
    }
});

ou

Executors.newCachedThreadPool().execute(new Runnable() {
    @Override
    public void run() {
        myCustomMethod();
    }
});

Cela fonctionnait parfaitement pour ce que je faisais. Nécessaire pour exécuter un service Web et mettre à jour une barre de progression simultanément à l'aide du modèle d'observateur.
— dpi

@Ashish: Veuillez expliquer ce qui a été modifié et pourquoi?
— MANN

1
@AshishAggarwal: Cela me semble bizarre quand quelqu'un fait ça sans prendre la permission de l'auteur!
— MANN

@MANN pouvez-vous expliquer pourquoi vous utilisez la méthode run dans le paramètre Thread? une meilleure performance?
— Asif Mushtaq

1
Avons-nous besoin de terminer explicitement le thread? N'y a-t-il pas un risque de créer une fuite de mémoire en ne mettant pas explicitement fin au thread? Ou le thread se termine-t-il une fois terminé run()?
— theyuv

59

Dans Java 8, vous pouvez le faire avec une seule ligne de code.

Si votre méthode ne prend aucun paramètre, vous pouvez utiliser une référence de méthode:

new Thread(MyClass::doWork).start();

Sinon, vous pouvez appeler la méthode dans une expression lambda:

new Thread(() -> doWork(someParam)).start();

désolé de le ramener mais qu'est-ce que cela ->signifie exactement ?
— Kyle

1
C'est la syntaxe utilisée pour créer une expression lambda. Jetez un œil à ces liens pour plus d'informations: Que fait «->» en Java? , et The Java ™ Tutorials - Lambda Expressions
— Aaron Cohn

@AaronCohn super homme! Connaissez-vous des alternatives aux threads en Java? Je viens du monde Python, où nous utiliserions Celery task queuepour des trucs asynchrones
— CESCO

Java a des abstractions de plus haut niveau pour traiter les threads , mais peut-être cherchez-vous quelque chose de plus comme Akka ?
— Aaron Cohn

8

Une autre option plus rapide pour appeler des choses (comme les DialogBoxes et MessageBoxes et la création de threads séparés pour les méthodes non thread-safe) serait d'utiliser l'expression Lamba

  new Thread(() -> {
                      "code here"
            }).start();

3

Il y a quelque temps, j'avais écrit une classe utilitaire simple qui utilise le service exécuteur JDK5 et exécute des processus spécifiques en arrière-plan. Étant donné que doWork () aurait généralement une valeur de retour void, vous souhaiterez peut-être utiliser cette classe d'utilitaire pour l'exécuter en arrière-plan.

Consultez cet article où j'avais documenté cet utilitaire.


6
Future et Callable font ce genre de chose pour vous.
— Amir Afghani

Oui, ils le font. l'idée ici est d'abstraire l'interface derrière un wrapper asynchrone.
— raja kolluru

Le lien est rompu (404).
— palacsint

3

Pour y parvenir avec RxJava 2.x, vous pouvez utiliser:

Completable.fromAction(this::dowork).subscribeOn(Schedulers.io().subscribe();

La subscribeOn()méthode spécifie sur quel planificateur exécuter l'action - RxJava a plusieurs planificateurs prédéfinis, y compris celui Schedulers.io()qui a un pool de threads destiné aux opérations d'E / S et celui Schedulers.computation()qui est destiné aux opérations gourmandes en CPU.


3

Si vous utilisez au moins Java 8, vous pouvez utiliser la méthode runAsyncde la classe CompletableFuture

CompletableFuture.runAsync(() -> {...});

Si vous devez renvoyer un résultat, utilisez à la supplyAsyncplace

CompletableFuture.supplyAsync(() -> 1);
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.