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).

Louis Rhys
la source
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.

Noel M
la source
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();
    }
});
MANN
la source
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();
Aaron Cohn
la source
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();
Rohan Sawant
la source
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.

raja kolluru
la source
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.

Clyde
la source
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);
k13i
la source