Jeder hier scheint zu denken, dass die Implementierung von Runnable der richtige Weg ist, und ich bin nicht wirklich anderer Meinung, aber meiner Meinung nach gibt es auch einen Grund, Thread zu erweitern. Tatsächlich haben Sie dies in Ihrem Code demonstriert.
Wenn Sie Runnable implementieren, hat die Klasse, die Runnable implementiert, keine Kontrolle über den Threadnamen. Es ist der aufrufende Code, der den Threadnamen wie folgt festlegen kann:
new Thread(myRunnable,"WhateverNameiFeelLike");
Wenn Sie jedoch Thread erweitern, können Sie dies innerhalb der Klasse selbst verwalten (genau wie in Ihrem Beispiel nennen Sie den Thread 'ThreadB'). In diesem Fall haben Sie:
A) könnte ihm einen nützlicheren Namen für Debugging-Zwecke geben
B) erzwingen, dass dieser Name für alle Instanzen dieser Klasse verwendet wird (es sei denn, Sie ignorieren die Tatsache, dass es sich um einen Thread handelt, und führen die obigen Schritte so aus, als ob es sich um eine ausführbare Datei handelt, aber wir sprechen hier auf jeden Fall über Konventionen ignoriere diese Möglichkeit, die ich fühle).
Sie können zum Beispiel sogar einen Stack-Trace seiner Erstellung nehmen und diesen als Thread-Namen verwenden. Dies mag seltsam erscheinen, kann jedoch je nach Struktur Ihres Codes für Debugging-Zwecke sehr nützlich sein.
Dies mag wie eine kleine Sache erscheinen, aber wenn Sie eine sehr komplexe Anwendung mit vielen Threads haben und plötzlich die Dinge "gestoppt" haben (entweder aus Gründen des Deadlocks oder möglicherweise aufgrund eines Fehlers in einem Netzwerkprotokoll, der geringer wäre Offensichtlich - oder aus anderen endlosen Gründen) ist es nicht immer sehr nützlich, einen Stack-Dump von Java zu erhalten, bei dem alle Threads als "Thread-1", "Thread-2" und "Thread-3" bezeichnet werden (dies hängt davon ab, wie Ihre Threads sind strukturiert und ob Sie anhand ihrer Stapelverfolgung sinnvoll erkennen können, welche welche ist - nicht immer möglich, wenn Sie Gruppen mit mehreren Threads verwenden, die alle denselben Code ausführen).
Allerdings können Sie dies natürlich auch generisch tun, indem Sie eine Erweiterung der Thread-Klasse erstellen, die ihren Namen auf einen Stack-Trace ihres Erstellungsaufrufs setzt, und diesen dann mit Ihren Runnable-Implementierungen anstelle der Standard-Java-Thread-Klasse verwenden (siehe unten) Zusätzlich zum Stack-Trace enthält der Thread-Name möglicherweise weitere kontextspezifische Informationen, die für das Debuggen nützlich sind (ein Verweis auf eine der vielen Warteschlangen oder Sockets, die beispielsweise verarbeitet werden könnten. In diesem Fall möchten Sie dies möglicherweise bevorzugen Erweitern Sie Thread speziell für diesen Fall, damit der Compiler Sie (oder andere Benutzer Ihrer Bibliotheken) zwingen kann, bestimmte Informationen (z. B. die betreffende Warteschlange / den betreffenden Socket) zur Verwendung im Namen zu übergeben.
Hier ist ein Beispiel für den generischen Thread mit dem aufrufenden Stack-Trace als Namen:
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 der 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]