it-swarm.com.de

Wie kann ich einen Parameter an einen Java-Thread übergeben?

Kann mir jemand vorschlagen, wie ich einem Thread einen Parameter übergeben kann?

Wie funktioniert es auch für anonyme Klassen?

253
Steve

Sie müssen den Parameter im Konstruktor an das ausführbare Objekt übergeben:

public class MyRunnable implements Runnable {

   public MyRunnable(Object parameter) {
       // store parameter for later user
   }

   public void run() {
   }
}

und ruf es so an:

Runnable r = new MyRunnable(param_value);
new Thread(r).start();
330
Alnitak

Für anonyme Klassen:

Als Antwort auf Fragenbearbeitungen funktioniert es für anonyme Klassen

   final X parameter = ...; // the final is important
   Thread t = new Thread(new Runnable() {
       p = parameter;
       public void run() { 
         ...
       };
   t.start();

Benannte Klassen:

Sie haben eine Klasse, die Thread erweitert (oder Runnable implementiert) und einen Konstruktor mit den Parametern, die Sie übergeben möchten. Wenn Sie dann den neuen Thread erstellen, müssen Sie die Argumente übergeben und den Thread dann wie folgt starten:

Thread t = new MyThread(args...);
t.start();

Runable ist eine viel bessere Lösung als Thread BTW. Also würde ich lieber:

   public class MyRunnable implements Runnable {
      private X parameter;
      public MyRunnable(X parameter) {
         this.parameter = parameter;
      }

      public void run() {
      }
   }
   Thread t = new Thread(new MyRunnable(parameter));
   t.start();

Diese Antwort ist im Grunde die gleiche wie diese ähnliche Frage: Wie werden Parameter an ein Thread-Objekt übergeben

101
Nick Fortescue

via Konstruktor einer Runnable- oder Thread-Klasse

class MyThread extends Thread {

    private String to;

    public MyThread(String to) {
        this.to = to;
    }

    @Override
    public void run() {
        System.out.println("hello " + to);
    }
}

public static void main(String[] args) {
    new MyThread("world!").start();
}
37
dfa

Wenn Sie einen Thread erstellen, benötigen Sie eine Instanz von Runnable. Die einfachste Möglichkeit, einen Parameter zu übergeben, besteht darin, ihn als Argument an den Konstruktor zu übergeben:

public class MyRunnable implements Runnable {

    private volatile String myParam;

    public MyRunnable(String myParam){
        this.myParam = myParam;
        ...
    }

    public void run(){
        // do something with myParam here
        ...
    }

}

MyRunnable myRunnable = new myRunnable("Hello World");
new Thread(myRunnable).start();

Wenn Sie den Parameter dann ändern möchten, während der Thread ausgeführt wird, können Sie Ihrer ausführbaren Klasse einfach eine Setter-Methode hinzufügen:

public void setMyParam(String value){
    this.myParam = value;
}

Sobald Sie dies haben, können Sie den Wert des Parameters ändern, indem Sie folgendermaßen aufrufen:

myRunnable.setMyParam("Goodbye World");

Wenn Sie eine Aktion auslösen möchten, wenn der Parameter geändert wird, müssen Sie natürlich Sperren verwenden, was die Komplexität erheblich erhöht.

16
jwoolard

Diese Antwort kommt sehr spät, aber vielleicht findet sie jemand nützlich. Es geht darum, einen Parameter an eine Runnable zu übergeben, ohne die benannte Klasse zu deklarieren (praktisch für Inliner):

String someValue = "Just a demo, really...";
new Thread(new Runnable() {
    private String myParam;
    public Runnable init(String myParam) {
        this.myParam = myParam;
        return this;
    }
    @Override
    public void run() {
        System.out.println("This is called from another thread.");
        System.out.println(this.myParam);
    }
}.init(someValue)).start();

Natürlich können Sie die Ausführung von start auf einen günstigeren oder angemessenen Zeitpunkt verschieben. Es liegt an Ihnen, was die Signatur der init-Methode sein wird (es kann also mehr und/oder unterschiedliche Argumente geben) und natürlich sogar ihren Namen, aber im Grunde erhalten Sie eine Idee.

Tatsächlich gibt es auch eine andere Möglichkeit, einen Parameter mit Hilfe der Initialisierungsblöcke an eine anonyme Klasse zu übergeben. Bedenken Sie:

String someValue = "Another demo, no serious thing...";
int anotherValue = 42;

new Thread(new Runnable() {
    private String myParam;
    private int myOtherParam;
    {
        this.myParam = someValue;
        this.myOtherParam = anotherValue;
    }
    @Override
    public void run() {
        System.out.println("This comes from another thread.");
        System.out.println(this.myParam + ", " + this.myOtherParam);
    }
}).start();

So geschieht alles innerhalb des Initialisierungsblocks.

15
Cromax

Um einen Thread zu erstellen, erstellen Sie normalerweise Ihre eigene Implementierung von Runnable. Übergeben Sie die Parameter an den Thread im Konstruktor dieser Klasse.

class MyThread implements Runnable{
   private int a;
   private String b;
   private double c;

   public MyThread(int a, String b, double c){
      this.a = a;
      this.b = b;
      this.c = c;
   }

   public void run(){
      doSomething(a, b, c);
   }
}
9
Mnementh

Sie können entweder die Threadclass oder die Runnableclass erweitern und Parameter nach Belieben angeben. In docs gibt es einfache Beispiele. Ich werde sie hier portieren:

 class PrimeThread extends Thread {
     long minPrime;
     PrimeThread(long minPrime) {
         this.minPrime = minPrime;
     }

     public void run() {
         // compute primes larger than minPrime
          . . .
     }
 }

 PrimeThread p = new PrimeThread(143);
 p.start();

 class PrimeRun implements Runnable {
     long minPrime;
     PrimeRun(long minPrime) {
         this.minPrime = minPrime;
     }

     public void run() {
         // compute primes larger than minPrime
          . . .
     }
 }


 PrimeRun p = new PrimeRun(143);
 new Thread(p).start();
8
bruno conde

Schreiben Sie entweder eine Klasse, die Runnable implementiert, und übergeben Sie alles, was Sie in einem entsprechend definierten Konstruktor benötigen, oder schreiben Sie eine Klasse, die Thread mit einem entsprechend definierten Konstruktor erweitert, der super () mit den entsprechenden Parametern aufruft.

7
PaulJWilliams

Ab Java 8 können Sie ein Lambda verwenden, um Parameter zu erfassen, die effektiv final sind. Zum Beispiel:

final String param1 = "First param";
final int param2 = 2;
new Thread(() -> {
    // Do whatever you want here: param1 and param2 are in-scope!
    System.out.println(param1);
    System.out.println(param2);
}).start();
5
Jeff G

Sie können eine Klasse von Runnable ableiten und den Parameter (zB) während der Konstruktion in übergeben.

Dann starten Sie es mit Thread.start (Runnable r);

Wenn Sie während den Thread bedeuten, halten Sie einfach einen Verweis auf Ihr abgeleitetes Objekt im aufrufenden Thread und rufen die entsprechenden Setter-Methoden auf (ggf. Synchronisierung)

3
Brian Agnew

Parameterübergabe über die Methoden start () und run ():

// Tester
public static void main(String... args) throws Exception {
    ThreadType2 t = new ThreadType2(new RunnableType2(){
        public void run(Object object) {
            System.out.println("Parameter="+object);
        }});
    t.start("the parameter");
}

// New class 1 of 2
public class ThreadType2 {
    final private Thread thread;
    private Object objectIn = null;
    ThreadType2(final RunnableType2 runnableType2) {
        thread = new Thread(new Runnable() {
            public void run() {
                runnableType2.run(objectIn);
            }});
    }
    public void start(final Object object) {
        this.objectIn = object;
        thread.start();
    }
    // If you want to do things like setDaemon(true); 
    public Thread getThread() {
        return thread;
    }
}

// New class 2 of 2
public interface RunnableType2 {
    public void run(Object object);
}
3
Java42

Es gibt eine einfache Möglichkeit, Parameter in Runables zu übergeben.

public void Function(final type variable) {
    Runnable runnable = new Runnable() {
        public void run() {
            //Code adding here...
        }
    };
    new Thread(runnable).start();
}
2
Chromium

In Java 8 können Sie lambda-Ausdrücke mit der Concurrency-API & der ExecutorService als übergeordneten Ersatz für direktes Arbeiten mit Threads verwenden:

newCachedThreadPool() Erstellt einen Thread-Pool, der neue Threads erstellt Bei Bedarf werden zuvor erstellte Threads jedoch wiederverwendet, wenn sie .__ sind. verfügbar. Diese Pools verbessern normalerweise die Leistung von Programmen, die viele kurzlebige asynchrone Aufgaben ausführen.

    private static final ExecutorService executor = Executors.newCachedThreadPool();

    executor.submit(() -> {
        myFunction(myParam1, myParam2);
    });

Siehe auch executorsjavadocs .

2
Stuart Cardall

Speziell für Android

Für Callback-Zwecke implementiere ich normalerweise mein eigenes generisches Runnable mit Eingabeparametern

public interface Runnable<TResult> {
    void run(TResult result);
}

Die Verwendung ist einfach:

myManager.doCallbackOperation(new Runnable<MyResult>() {
    @Override
    public void run(MyResult result) {
        // do something with the result
    }
});

Im Manager:

public void doCallbackOperation(Runnable<MyResult> runnable) {
    new AsyncTask<Void, Void, MyResult>() {
        @Override
        protected MyResult doInBackground(Void... params) {
            // do background operation
            return new MyResult(); // return resulting object
        }

        @Override
        protected void onPostExecute(MyResult result) {
            // execute runnable passing the result when operation has finished
            runnable.run(result);
        }
    }.execute();
}
1
Andrei

Nein, Sie können keine Parameter an die run()-Methode übergeben. Die Signatur sagt Ihnen das (es hat keine Parameter). Der einfachste Weg, dies zu tun, wäre wahrscheinlich die Verwendung eines speziell erstellten Objekts, das einen Parameter im Konstruktor übernimmt und in einer finalen Variablen speichert: 

public class WorkingTask implements Runnable
{
    private final Object toWorkWith;

    public WorkingTask(Object workOnMe)
    {
        toWorkWith = workOnMe;
    }

    public void run()
    {
        //do work
    }
}

//...
Thread t = new Thread(new WorkingTask(theData));
t.start();

Sobald Sie das getan haben, müssen Sie auf die Datenintegrität des Objekts achten, das Sie in die 'WorkingTask' übergeben. Die Daten sind jetzt in zwei verschiedenen Threads vorhanden, Sie müssen also sicherstellen, dass sie Thread-Safe sind.

1
Mihir Patel

Eine weitere Option; Mit diesem Ansatz können Sie das ausführbare Element wie einen asynchronen Funktionsaufruf verwenden. Wenn Ihre Aufgabe kein Ergebnis zurückgeben muss, z. Es führt nur eine Aktion aus, die Sie nicht befürchten müssen, wie Sie ein "Ergebnis" zurückgeben.

Mit diesem Muster können Sie ein Element wiederverwenden, wenn Sie einen internen Status benötigen. Wenn Parameter nicht im Konstruktor übergeben werden, ist Vorsicht geboten, um den Zugriff der Programme auf Parameter zu vermitteln. Möglicherweise müssen Sie weitere Überprüfungen durchführen, wenn Ihr Anwendungsfall verschiedene Anrufer usw. umfasst.

public class MyRunnable implements Runnable 
{
  private final Boolean PARAMETER_LOCK  = false;
  private X parameter;

  public MyRunnable(X parameter) {
     this.parameter = parameter;
  }

  public void setParameter( final X newParameter ){

      boolean done = false;
      synchronize( PARAMETER_LOCK )
      {
          if( null == parameter )
          {
              parameter = newParameter;
              done = true;
          }
      }
      if( ! done )
      {
          throw new RuntimeException("MyRunnable - Parameter not cleared." );
      }
  }


  public void clearParameter(){

      synchronize( PARAMETER_LOCK )
      {
          parameter = null;
      }
  }


  public void run() {

      X localParameter;

      synchronize( PARAMETER_LOCK )
      {
          localParameter = parameter;
      }

      if( null != localParameter )
      {
         clearParameter();   //-- could clear now, or later, or not at all ...
         doSomeStuff( localParameter );
      }

  }

}

Thread t = neuer Thread (neuer MyRunnable (Parameter)); t.start ();

Wenn Sie ein Ergebnis der Verarbeitung benötigen, müssen Sie auch die Fertigstellung von MyRunnable koordinieren, wenn die Unteraufgabe abgeschlossen ist. Sie könnten einen Rückruf weiterleiten oder einfach auf den Thread 't' warten usw.

1
will

Ich weiß, dass ich einige Jahre zu spät komme, aber ich bin auf dieses Problem gestoßen und habe einen unorthodoxen Ansatz gewählt. Ich wollte es machen, ohne eine neue Klasse zu machen. 

int x = 0;
new Thread((new Runnable() {
     int x;
     public void run() {
        // stuff with x and whatever else you want
     }
     public Runnable pass(int x) {
           this.x = x;
           return this;
     }
}).pass(x)).start();
0
Meyi

Erstellen Sie in Ihrer Klasse eine lokale Variable, die extends Thread oder implements Runnable ist.

public class Extractor extends Thread {
    public String webpage = "";
    public Extractor(String w){
        webpage = w;
    }
    public void setWebpage(String l){
        webpage = l;
    }

    @Override
    public void run() {// l is link
        System.out.println(webpage);
    }
    public String toString(){
        return "Page: "+webpage;
    }}

Auf diese Weise können Sie eine Variable übergeben, wenn Sie sie ausführen.

Extractor e = new Extractor("www.google.com");
e.start();

Die Ausgabe:

"www.google.com"
0
calthecoder