6 Stimmen

Wiederverwendung von Java-Threads über Executor

Ich bin verwirrt über die folgenden Punkte:
Um Threads in einem Java-Programm zu verwenden, ist es am einfachsten, die Klasse Thread zu erweitern und die Schnittstelle runnable zu implementieren (oder einfach runnable zu implementieren).
Um die Ausführung des Threads zu starten, müssen wir die Methode start() des Threads aufrufen, die wiederum die Methode run() des Threads aufruft. Und so startet der Thread.
Die Methode start() (wenn ich mich nicht irre) muss genau und nur einmal aufgerufen werden für jeden Faden. Infolgedessen können Thread-Instanzen nicht wiederverwendet werden, es sei denn, die Run-Methode selbst läuft in einer Art Endlosschleife, die eine benutzerdefinierte Implementierung der Wiederverwendung des Threads ermöglicht.
Jetzt die Javadoc Linktext sagt

Bei Aufrufen zur Ausführung werden zuvor erstellte Threads wiederverwendet, falls vorhanden.

Ich verstehe nicht, wie dies umgesetzt wird. Ich stelle in der Execute-Methode der Executor-Methode meinen eigenen Thread zur Verfügung, z.B.

  ExecutorService myCachedPool = Executors.newCachedThreadPool();
  myCachedPool.execute(new Runnable(){public void run(){  
     //do something time consuming

  }});

Wie kann dieser benutzerdefinierte Thread, den ich dem Executor-Framework zugewiesen habe, wiederverwendet werden?
Ist es Executor erlaubt, die Methode start() mehr als 1 Mal aufzurufen, während wir dies in unseren Programmen nicht dürfen? Habe ich etwas falsch verstanden?

Ich danke Ihnen.

5voto

Jon Skeet Punkte 1325502

Beachten Sie, dass es sich nicht um Executor das ruft start() - Es ist ExecutorService . Und nein, es ruft nicht an start() zweimal. Es startet nicht die Aufgabe, die Sie ihm direkt mit Thread.start() ... stattdessen wird ein Thread gestartet, der die Warteschlange des Threadpools kennt. Der Thread wartet im Grunde genommen, bis es etwas zu tun gibt, holt es dann ab und führt es aus, bevor er wieder zu warten beginnt. Obwohl der Thread also mehrere Aufgaben ausführt, Thread.start() wird nur einmal aufgerufen.

EDIT: Den Kommentaren nach zu urteilen, sind Sie etwas verwirrt über den Unterschied zwischen einer Runnable (das ist eine auszuführende Aufgabe) und eine Thread (das ist die Ausführung der Aufgaben).

Ein und derselbe Thread kann mehrere Aufgaben ausführen. Ein sehr einfaches Beispiel, bei dem kein Thread-Pool verwendet wird, ist das folgende:

public class MultiRunnable implements Runnable
{
    private final List<Runnable> runnables;

    public MultiRunnable(List<Runnable> runnables)
    {
        this.runnables = runnables;
    }

    public void run()
    {
        for (Runnable runnable : runnables)
        {
             runnable.run();
        }
    }
}

(Ignorieren Sie die potenziellen Probleme der Threadsicherheit bei der Verwendung einer List<T> aus mehreren Threads).

Sie könnten eine ganze Reihe von Runnable Aufgaben, die verschiedene Dinge tun können, und erstellen Sie dann eine einzige MultiRunnable um sie nacheinander auszuführen. Übergeben Sie diese Instanz von MultiRunnable in die Thread Konstruktor, und wenn Sie dann den Thread starten, wird er jede der ursprünglich ausführbaren Aufgaben ausführen. Ist das hilfreich?

5voto

jbindel Punkte 5367

Er ruft start() nicht mehr als einmal auf; stattdessen wird der Thread im Pool nie beendet, sondern bleibt einfach am Leben - er wartet. Der Quellcode steht zum Download zur Verfügung, wenn Sie ihn sich ansehen möchten.

Jeder Thread im Thread-Pool kann einfach wait() dass der Executor ihm ein neues Runnable aushändigt, aber der Thread selbst run() Methode noch nicht abgeschlossen ist. Sie wartet lediglich darauf, dass ein neues Runnable an den Executor übergeben wird.

1voto

Leo Izen Punkte 4125

Um einen Thread mehr als einmal zu "starten", erstellen Sie ein Runnable. Zum Beispiel:

//NO
private class T extends Thread { //not necessary to implement runnable
    public void run(){
        //...
    }
}
void someMethod(){
    T a = new T();
    a.start();
    a.start(); //NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO
}

Stattdessen,

//Yes
private class T implements Runnable {
    public void run(){
        //...
    }
}
void someMethod(){
    T a = new T();
    new Thread(a).start();
    new Thread(a).start(); //YES YES YES
}

Auch dies ist möglich:

void someMethod(){
    final Runnable r = new Runnable(){
        public void run(){
            //...
        }
    };
    new Thread(r).start();
    new Thread(r).start();
}
// r could also be a field of you class.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X