Come chiamare un metodo con un thread separato in Java?


126

diciamo che ho un metodo doWork(). Come lo chiamo da un thread separato (non il thread principale).


Ci sono stati alcuni esempi su questa recente domanda correlata: uccidere un ciclo infinito in java
Greg Hewgill

stackoverflow.com/questions/36832094/… Ho un problema simile per favore aiutami a risolverlo
Sruthi Acg

Potresti anche dare un'occhiata a Reactive Java blog.danlew.net/2014/09/15/grokking-rxjava-part-1 per attività asincrone
Nathan Dunn

Risposte:


138

Crea una classe che implementa l' Runnableinterfaccia. Inserisci il codice che vuoi eseguire nel run()metodo: questo è il metodo che devi scrivere per essere conforme Runnableall'interfaccia. Nel tuo thread "principale", crea una nuova Threadclasse, passando al costruttore una tua istanza Runnable, quindi chiamala start(). startdice alla JVM di fare la magia per creare un nuovo thread e quindi chiamare il tuo runmetodo in quel nuovo 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();
    }    
}

Dai un'occhiata al tutorial sulla concorrenza di Java per iniziare.

Se il tuo metodo verrà chiamato frequentemente, potrebbe non valere la pena creare un nuovo thread ogni volta, poiché si tratta di un'operazione costosa. Probabilmente sarebbe meglio usare un pool di thread di qualche tipo. Date un'occhiata a Future, Callable, Executorclassi nel java.util.concurrentpacchetto.


1
cosa succede se c'è una variabile che vorresti passare?
Louis Rhys

8
Il run()metodo non accetta parametri, quindi non puoi passare una variabile lì. Suggerirei di passarlo nel costruttore: modificherò la mia risposta per dimostrarlo.
Noel M

1
C'è un modo breve per chiamare 1 metodo in un thread diverso? Conosco la new Thread() { public void run() {myMethod();}}.start();strada, è la più breve?
Steven Roose

@NoelM puoi spiegare la differenza tra la tua e la risposta del MANN?
Asif Mushtaq

2
La risposta di MANN utilizza un'implementazione anonima di Runnable: la mia è una classe che si estende Runnable. E poiché l'ho fatto, ho il mio costruttore che passa lo stato nell'oggetto istanziato.
Noel M

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

o

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

o

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

o

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

o

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

Funzionava perfettamente per quello che stavo facendo. Necessario per eseguire un servizio web e aggiornare una barra di avanzamento contemporaneamente utilizzando il modello osservatore.
dpi

@ Ashish: Spiega cosa e perché è stato modificato?
MANN

1
@ AshishAggarwal: Mi sembra strano quando qualcuno lo fa senza il permesso dell'autore!
MANN

@MANN puoi spiegare perché usi il metodo run nel parametro Thread? qualche prestazione migliore?
Asif Mushtaq

1
Abbiamo bisogno di terminare esplicitamente il thread? Non c'è il rischio di creare una perdita di memoria non terminando esplicitamente il thread? O il thread termina quando ha finito run()?
theyuv

59

In Java 8 puoi farlo con una riga di codice.

Se il tuo metodo non accetta parametri, puoi utilizzare un metodo di riferimento:

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

Altrimenti, puoi chiamare il metodo in un'espressione lambda:

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

mi dispiace riportarlo, ma cosa significa esattamente ->?
Kyle

1
Questa è la sintassi utilizzata per creare un'espressione lambda. Dai un'occhiata a questi link per maggiori informazioni: Cosa fa '->' in Java? e The Java ™ Tutorials - Lambda Expressions
Aaron Cohn

@AaronCohn grande roba uomo! Conosci qualche alternativa ai thread in Java? Vengo dal mondo Python, dove Celery task queue
useremmo

Java ha astrazioni di livello superiore per gestire i thread , ma forse stai cercando qualcosa di più simile ad Akka ?
Aaron Cohn

8

Un'altra opzione più rapida per chiamare cose (come DialogBoxes e MessageBoxes e creare thread separati per metodi non thread-safe) sarebbe quella di utilizzare Lamba Expression

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

3

Qualche tempo fa, avevo scritto una semplice classe di utilità che utilizza il servizio esecutore JDK5 ed esegue processi specifici in background. Poiché doWork () in genere avrebbe un valore di ritorno void, potresti voler utilizzare questa classe di utilità per eseguirlo in background.

Vedi questo articolo in cui avevo documentato questa utility.


6
Future e Callable fanno questo genere di cose per te.
Amir Afghani

Sì, lo fanno. l'idea qui è di astrarre l'interfaccia dietro un wrapper asincrono.
raja kolluru

Il collegamento è interrotto (404).
palacsint

3

Per ottenere ciò con RxJava 2.x puoi utilizzare:

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

Il subscribeOn()metodo specifica su quale scheduler eseguire l'azione - RxJava ha diversi scheduler predefiniti, incluso il Schedulers.io()quale ha un pool di thread destinato alle operazioni di I / O e Schedulers.computation()che è inteso per le operazioni a uso intensivo della CPU.


3

Se stai usando almeno Java 8 puoi usare il metodo runAsyncdella classe CompletableFuture

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

Se devi restituire un risultato, usa supplyAsyncinvece

CompletableFuture.supplyAsync(() -> 1);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.