Todos aquí parecen pensar que implementar Runnable es el camino a seguir y realmente no estoy en desacuerdo con ellos, pero también hay un caso para extender Thread, en mi opinión, de hecho lo has demostrado en tu código.
Si implementa Runnable, entonces la clase que implementa Runnable no tiene control sobre el nombre del subproceso, es el código de llamada que puede establecer el nombre del subproceso, así:
new Thread(myRunnable,"WhateverNameiFeelLike");
pero si extiende Thread, entonces puede administrar esto dentro de la clase en sí (al igual que en su ejemplo, llama al hilo 'ThreadB'). En este caso usted:
A) podría darle un nombre más útil para fines de depuración
B) están obligando a que ese nombre se use para todas las instancias de esa clase (a menos que ignore el hecho de que es un hilo y haga lo anterior con él como si fuera un Runnable, pero estamos hablando de convenciones aquí, en cualquier caso, también puede ignorar esa posibilidad que siento).
Incluso podría, por ejemplo, tomar un rastro de la pila de su creación y usarlo como el nombre del hilo. Esto puede parecer extraño, pero dependiendo de cómo esté estructurado su código, puede ser muy útil para la depuración.
Esto puede parecer algo pequeño, pero cuando tiene una aplicación muy compleja con muchos subprocesos y de repente las cosas 'se han detenido' (ya sea por un punto muerto o posiblemente debido a una falla en un protocolo de red que sería menos obvio, u otras razones interminables), entonces obtener un volcado de pila de Java donde todos los hilos se llaman 'Thread-1', 'Thread-2', 'Thread-3' no siempre es muy útil (depende de cómo sean sus hilos estructurado y si puede decir de manera útil cuál es cuál solo por su seguimiento de la pila, no siempre es posible si está utilizando grupos de múltiples subprocesos que ejecutan el mismo código).
Dicho esto, por supuesto, también puede hacer lo anterior de manera genérica creando una extensión de la clase de subproceso que establece su nombre en un seguimiento de la pila de su llamada de creación y luego usarlo con sus implementaciones Runnable en lugar de la clase estándar de subprocesos de Java (consulte a continuación), pero además del seguimiento de la pila, puede haber más información específica del contexto que sería útil en el nombre del hilo para la depuración (una referencia a una de las muchas colas o sockets que podría procesar, por ejemplo, en cuyo caso puede preferir extienda Thread específicamente para ese caso para que el compilador lo obligue (u otros que usan sus bibliotecas) a pasar cierta información (por ejemplo, la cola / socket en cuestión) para usar en el nombre).
Aquí hay un ejemplo del hilo genérico con el seguimiento de la pila de llamadas como su nombre:
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"));
}
}
y aquí hay una muestra de la salida que compara los dos nombres:
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]