Jeder hier scheint zu denken, dass die Implementierung von Runnable ist der Weg zu gehen, und ich nicht wirklich mit ihnen zu widersprechen, aber es gibt auch ein Fall für die Erweiterung Thread meiner Meinung nach, in der Tat haben Sie Art von es in Ihrem Code demonstriert.
Wenn Sie Runnable implementieren, dann hat die Klasse, die Runnable implementiert, keine Kontrolle über den Thread-Namen, es ist der aufrufende Code, der den Thread-Namen festlegen kann:
new Thread(myRunnable,"WhateverNameiFeelLike");
aber wenn Sie Thread erweitern, können Sie dies innerhalb der Klasse selbst verwalten (so wie Sie in Ihrem Beispiel den Thread 'ThreadB' nennen). In diesem Fall Sie:
A) könnte für die Fehlersuche einen nützlicheren Namen erhalten
B) erzwingen, dass dieser Name für alle Instanzen dieser Klasse verwendet wird (es sei denn, Sie ignorieren die Tatsache, dass es ein Thread ist und tun das oben genannte mit ihm, als ob es ein Runnable ist, aber wir sprechen hier über Konvention in jedem Fall so kann ignorieren, dass Möglichkeit ich denke).
Sie können sogar einen Stack-Trace der Erstellung des Threads nehmen und diesen als Thread-Namen verwenden. Dies mag seltsam erscheinen, aber je nachdem, wie Ihr Code strukturiert ist, kann es für die Fehlersuche sehr nützlich sein.
Dies mag wie eine Kleinigkeit erscheinen, aber wenn Sie eine sehr komplexe Anwendung mit vielen Threads haben und plötzlich alles "stehen geblieben" ist (entweder aus Gründen eines Deadlocks oder möglicherweise wegen eines Fehlers in einem Netzwerkprotokoll, der weniger offensichtlich ist - oder aus anderen endlosen Gründen), dann ist es nicht immer sehr nützlich, einen Stackdump von Java zu erhalten, in dem alle Threads "Thread-1" genannt werden, Thread-2','Thread-3' heißen, ist nicht immer sehr nützlich (es hängt davon ab, wie Ihre Threads strukturiert sind und ob Sie anhand des Stack Trace erkennen können, welcher Thread welcher ist - was nicht immer möglich ist, wenn Sie Gruppen von mehreren Threads verwenden, die alle denselben Code ausführen).
Sie könnten das oben Gesagte natürlich auch auf generische Weise tun, indem Sie eine Erweiterung der Thread-Klasse erstellen, die ihren Namen auf einen Stack-Trace ihres Erstellungsaufrufs setzt, und diese dann mit Ihren Runnable-Implementierungen anstelle der Standard-Java-Thread-Klasse verwenden (siehe unten). Kontext-spezifische Informationen, die im Thread-Namen für die Fehlersuche nützlich wären (ein Verweis auf eine der vielen Warteschlangen oder Sockets, die er zum Beispiel verarbeiten könnte, in welchem Fall Sie es vorziehen könnten, Thread speziell für diesen Fall zu erweitern, so dass Sie den Compiler dazu zwingen können, Ihnen (oder anderen, die Ihre Bibliotheken verwenden) bestimmte Informationen zu übergeben (z. B. die Warteschlange/den Socket, die/den er verarbeitet). z. B. die betreffende Warteschlange/Socket) zur Verwendung im Namen).
Hier ist ein Beispiel für einen generischen Thread mit dem Namen der aufrufenden Stapelverfolgung:
public class DebuggableThread extends Thread {
private static String getStackTrace(String name) {
Throwable t= new Throwable("DebuggableThread-"+name);
ByteArrayOutputStream os = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(os);
t.printStackTrace(ps);
return os.toString();
}
public DebuggableThread(String name) {
super(getStackTrace(name));
}
public static void main(String[] args) throws Exception {
System.out.println(new Thread());
System.out.println(new DebuggableThread("MainTest"));
}
}
und hier ist ein Beispiel für die Ausgabe, in der die beiden Namen verglichen werden:
Thread[Thread-1,5,main]
Thread[java.lang.Throwable: DebuggableThread-MainTest
at DebuggableThread.getStackTrace(DebuggableThread.java:6)
at DebuggableThread.<init>(DebuggableThread.java:14)
at DebuggableThread.main(DebuggableThread.java:19)
,5,main]
66 Stimmen
Vielen Dank für diese Frage, die Antworten haben eine Menge Missverständnisse, die ich hatte, aufgeklärt. Ich schaute in den richtigen Weg, um Java-Threads zu tun, bevor SO existierte und es gab eine Menge von Fehlinformationen / veraltete Informationen da draußen.
5 Stimmen
Gibt es einen Grund, warum Sie den Thread ( aber ich empfehle es nicht ), können Sie präventiv mit
interrupt()
. Auch hier handelt es sich um eine Idee, die im richtigen Fall nützlich sein könnte, aber ich empfehle sie nicht.0 Stimmen
Bitte lesen Sie auch die Antwort, die sehr gut erklärt ist: stackoverflow.com/q/5562720/285594
0 Stimmen
@bestsss, ich versuche herauszufinden, was Sie mit der Behandlung von interrupt() meinen könnten. Versuchen Sie, die Methode zu überschreiben?
0 Stimmen
@Bob, ja bob. Java macht das natürlich für
java.nio.channels.InterruptibleChannel
(s) Sie können einen Blick auf die Impl. von Thread.interrupt() werfen. Mit Hilfe der Hilfe voninterrupt()
caller ist eine Idee und ein nützlicher Ansatz, der wiederum nicht für Anfänger empfohlen wird.0 Stimmen
@Bob, es gibt noch eine andere Möglichkeit, nämlich die Erweiterung
java.nio.channels.spi.AbstractSelector
und außer Kraft setzenwakeup()
aber das ist eine viel zu schmutzige Art, den Fall zu beurteilen :)8 Stimmen
Ja, laut Code kann die Klasse Thread A jede Klasse erweitern, während die Klasse Thread B keine andere Klasse erweitern kann.
0 Stimmen
Sollte bei der Implementierung eines Callback über Runnable jetzt aussehen.
0 Stimmen
@RichieHH - das kommt darauf an. Rufen Sie nur zurück, wenn Sie einen Rückruf benötigen. Das heißt, wenn der laufende Code (die
Runnable
in OP) muss die Logik im Aufrufer ausführen.0 Stimmen
Lasse ich den Lauf leer? Wenn ich Funktionen verwende, laufen sie dann in einem anderen Thread?
0 Stimmen
Komposition ist im objektorientierten Design der Vererbung vorzuziehen
0 Stimmen
Verwenden Sie nicht direkt Thread, sollten Sie ExecutorService verwenden, die für bessere Tests gespottet werden kann
0 Stimmen
Erweitern Sie Thread, wenn Sie die Art und Weise, wie Thread sich verhält, VERÄNDERN wollen. Implementieren Sie runnable, wenn Sie einen anderen Thread erweitern müssen. Wenn Sie ein Objekt zwischen Threads teilen müssen, ist Runnable der richtige Weg, da Thread dies nicht erlaubt. Wenn keiner der beiden Fälle zutrifft, ist Runnable semantisch korrekter, obwohl dieser letzte Punkt nicht sehr wichtig ist, da jemand denken könnte, dass Sie das Verhalten von Thread geändert haben, wenn Sie ihn erweitern, obwohl Sie das nicht tun.