Kann mir jemand vorschlagen, wie ich einen Parameter an einen Thread übergeben kann?
Und wie funktioniert das bei anonymen Klassen?
Kann mir jemand vorschlagen, wie ich einen Parameter an einen Thread übergeben kann?
Und wie funktioniert das bei anonymen Klassen?
Sie müssen den Parameter im Konstruktor an das Runnable-Objekt übergeben:
public class MyRunnable implements Runnable {
public MyRunnable(Object parameter) {
// store parameter for later user
}
public void run() {
}
}
und rufen ihn so auf:
Runnable r = new MyRunnable(param_value);
new Thread(r).start();
Das bedeutet, dass jeder Thread, der mit r
haben das gleiche Argument. Wenn wir also verschiedene Argumente an mehrere Threads übergeben wollen, die MyThread
müssten wir eine neue MyThread
Instanz unter Verwendung des gewünschten Arguments für jeden Thread. Mit anderen Worten: Um einen Thread zum Laufen zu bringen, müssen wir zwei Objekte erstellen: Thread und MyThread. Ist das aus Sicht der Leistung schlecht?
@IsaacKleinman Nun, das muss man sowieso tun, es sei denn, man erweitert den Thread. Und diese Lösung funktioniert auch in diesem Fall - ändern Sie einfach "implements Runnable" in "extends Thread", "Runnable" in "Thread", und "new Thread(r)" in "r".
Als Antwort auf die Frage "Editieren": So 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();
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 dann den Thread starten, etwa so:
Thread t = new MyThread(args...);
t.start();
Runnable ist im Übrigen eine viel bessere Lösung als Thread. Ich würde also bevorzugen:
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 die ähnliche Frage: Wie man Parameter an ein Thread-Objekt übergibt
Ich habe Code, der Ihrem Beispiel einer anonymen Klasse ähnelt, außer dass ich auf parameter
direkt vom run()
Methode ohne Verwendung eines Feldes wie p
überhaupt nicht. Es scheint zu funktionieren. Gibt es irgendeine subtile Multithreading-Sache, die ich verpasse, weil ich nicht kopiere parameter
a p
vorher?
Ich hatte die gleiche Erfahrung wie @RandallCook für die Klasse Anonymous. Solange ich die final X parameter
vor dem new Runnable()
Zeile, dann könnte ich auf parameter
innerhalb run()
. Ich brauchte nicht die Extrakosten zu machen. p = parameter
.
Diese Antwort kommt sehr spät, aber vielleicht findet sie jemand nützlich. Es geht darum, wie man einen oder mehrere Parameter an eine Runnable
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 angemesseneren Zeitpunkt verschieben. Und es liegt an Ihnen, was die Unterschrift des init
Methode (sie kann also mehr und/oder andere Argumente annehmen) und natürlich auch ihren Namen, aber im Grunde haben Sie eine Vorstellung davon.
Es gibt noch eine weitere Möglichkeit, einen Parameter an eine anonyme Klasse zu übergeben, und zwar mit Hilfe der Initialisierungsblöcke. Betrachten Sie dies:
String someValue = "Another demo, no serious thing...";
int anotherValue = 42;
new Thread(new Runnable() {
private String myParam;
private int myOtherParam;
// instance initializer
{
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();
Alles geschieht also innerhalb des Initialisierungsblocks.
Dieses letzte Beispiel hat mir eigentlich ganz gut gefallen. Erinnert mich an die Verwendung einer Schließung in JS, um Variablen in den äußeren Bereich zu verweisen. Aber ist die this.myParam
dann wirklich notwendig? Könnte man nicht einfach die privaten Variablen weglassen und sich auf die Variable aus dem äußeren Bereich beziehen? Ich verstehe (natürlich), dass dies einige Auswirkungen hat, z. B. dass die Variable nach dem Starten des Threads noch geändert werden kann.
Wenn Sie einen Thread erstellen, benötigen Sie eine Instanz von Runnable
. Der einfachste Weg, einen Parameter zu übergeben, wäre, 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 dann den Parameter ändern wollen, während der Thread läuft, können Sie einfach eine Setter-Methode zu Ihrer runnable-Klasse hinzufügen:
public void setMyParam(String value){
this.myParam = value;
}
Sobald Sie dies haben, können Sie den Wert des Parameters ändern, indem Sie wie folgt aufrufen:
myRunnable.setMyParam("Goodbye World");
Wenn Sie eine Aktion auslösen wollen, wenn der Parameter geändert wird, müssen Sie natürlich Sperren verwenden, was die Sache wesentlich komplexer macht.
Führt das Hinzufügen eines Setzers nicht zu potenziellen Wettlaufbedingungen? Wenn der Thread mit der Variablen als einem Wert beginnt, aber der Setter ihn mitten in der Ausführung ändert, wäre das nicht problematisch?
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.
6 Stimmen
Könnten Sie vielleicht noch etwas mehr dazu sagen, was genau Sie zu tun versuchen? Es gibt viele verschiedene Techniken, die aber alle vom Endziel abhängen.
4 Stimmen
Meinen Sie die Übergabe eines Parameters an einen bereits laufenden Thread? Denn in allen aktuellen Antworten geht es um die Übergabe von Parametern an neue Threads...
0 Stimmen
Jetzt können Sie
Consumer<T>
.