Ich benötige ein "Runnable, das einen Parameter akzeptiert", obwohl ich weiß, dass ein solches Runnable nicht wirklich existiert.
Dies kann auf einen grundlegenden Fehler im Design meiner App und / oder auf eine mentale Blockade in meinem müden Gehirn hinweisen. Ich hoffe, hier einige Ratschläge zu finden, wie Sie Folgendes erreichen können, ohne grundlegende OO-Prinzipien zu verletzen:
private Runnable mOneShotTask = new Runnable(String str) {
public void run(String str) {
someFunc(str);
}
};
Irgendeine Idee, wie man so etwas wie das oben Genannte erreicht?
Consumer<T>
.Consumer<T>
Antworten:
Nun, es ist fast 9 Jahre her, seit ich das ursprünglich gepostet habe und um ehrlich zu sein, hat Java seitdem ein paar Verbesserungen vorgenommen. Ich werde meine ursprüngliche Antwort unten belassen, aber die Leute müssen nicht tun, was darin enthalten ist. Vor 9 Jahren hätte ich mich bei der Codeüberprüfung gefragt, warum sie es getan haben, und es vielleicht genehmigt, vielleicht auch nicht. Angesichts der Verfügbarkeit moderner Lambdas ist es unverantwortlich, eine so hoch bewertete Antwort zu haben, in der ein veralteter Ansatz empfohlen wird (der fairerweise zunächst zweifelhaft war ...). Im modernen Java würde diese Codeüberprüfung sofort abgelehnt, und dies wäre der Fall empfohlen:
Nach wie vor werden Details wie der sinnvolle Umgang mit diesem Thread dem Leser als Übung überlassen. Aber um es ganz klar auszudrücken: Wenn Sie Angst vor der Verwendung von Lambdas haben, sollten Sie noch mehr Angst vor Multithread-Systemen haben.
Ursprüngliche Antwort, nur weil:
Sie können eine Klasse direkt in der Methode deklarieren
quelle
Sie könnten es in eine Funktion setzen.
(Als ich dies verwendete, war mein Parameter eine Ganzzahl-ID, mit der ich eine Hashmap von ID -> myRunnables erstellt habe. Auf diese Weise kann ich die Hashmap verwenden, um verschiedene myRunnable-Objekte in einem Handler zu veröffentlichen / zu entfernen.)
quelle
Runnable
von der Methode zurückgegebenes Objekt irgendwo vorhanden ist, kannparamStr
es wahrscheinlich nicht zur Speicherbereinigung verwendet werden. Es ist möglich, dass die JIT (oder sogar javac), wenn das Objekt vorhanden ist, aber nie wieder ausgeführt werden kann, beschließt, es aus dem Bereich zu entfernen. Wir sollten uns jedoch nicht auf solche Optimierungen verlassen, da sie sich in Zukunft ändern können.Erstellen Sie eine Init-Funktion, die das Objekt selbst zurückgibt, und initialisieren Sie damit die Parameter.
quelle
Ich verwende die folgende Klasse, die die Runnable- Schnittstelle implementiert . Mit dieser Klasse können Sie einfach neue Threads mit Argumenten erstellen
quelle
public RunnableArg(Object... args) { setArgs(args); }
dann die lokale Klasse zu beschreiben:class ActionArg extends RunnableArg { public ActionArg(Object... arg) { super(arg); } @Override public void run() { /* getArgs() and process them */ } }
und benutze ihnThread t = new Thread(new ActionArg( %param_object(s)% )); t.start();
Sie haben zwei Möglichkeiten:
Definieren Sie eine benannte Klasse. Übergeben Sie Ihren Parameter an den Konstruktor der benannten Klasse.
Lassen Sie Ihre anonyme Klasse über Ihrem "Parameter" schließen. Stellen Sie sicher, dass Sie es als markieren
final
.quelle
Seit Java 8 ist die beste Antwort
Consumer<T>
:https://docs.oracle.com/javase/8/docs/api/java/util/function/Consumer.html
Es ist eine der funktionalen Schnittstellen, was bedeutet, dass Sie es als Lambda-Ausdruck bezeichnen können:
quelle
Ich möchte zuerst wissen, was Sie hier erreichen möchten, damit ein Argument an new Runnable () oder run () übergeben werden muss. Der übliche Weg sollte darin bestehen, ein ausführbares Objekt zu haben, das Daten (str) an seine Threads übergibt, indem vor dem Start Mitgliedsvariablen festgelegt werden. Die run () -Methode verwendet dann diese Mitgliedsvariablenwerte, um someFunc () auszuführen.
quelle