Кажется, все здесь думают, что реализация Runnable - это путь, и я на самом деле не согласен с ними, но, на мой взгляд, есть также причина для расширения Thread, фактически вы как бы продемонстрировали это в своем коде.
Если вы реализуете Runnable, то класс, реализующий Runnable, не будет контролировать имя потока, это вызывающий код, который может установить имя потока, например, так:
new Thread(myRunnable,"WhateverNameiFeelLike");
но если вы расширяете Thread, тогда вы можете управлять этим внутри самого класса (как в вашем примере вы называете поток «ThreadB»). В этом случае вы:
А) может дать ему более полезное имя для целей отладки
B) принуждают использовать это имя для всех экземпляров этого класса (если вы не игнорируете тот факт, что он является потоком, и делаете вышеизложенное с ним, как будто это Runnable, но мы говорим о соглашении здесь в любом случае, так что можно игнорировать эту возможность я чувствую).
Вы можете даже, например, взять трассировку стека его создания и использовать его в качестве имени потока. Это может показаться странным, но в зависимости от структуры вашего кода это может быть очень полезно для целей отладки.
Это может показаться мелочью, но когда у вас очень сложное приложение с большим количеством потоков и все внезапно «остановилось» (либо по причине тупиковой ситуации, либо, возможно, из-за недостатка сетевого протокола, который был бы меньше очевидно - или по другим бесконечным причинам) затем получение дампа стека из Java, где все потоки называются «Thread-1», «Thread-2», «Thread-3», не всегда очень полезно (это зависит от того, как ваши потоки структурирован и можете ли вы с пользой определить, что есть что, просто по их трассировке стека - не всегда возможно, если вы используете группы из нескольких потоков, все выполняющие один и тот же код).
Сказав, что вы, конечно, также можете сделать вышеупомянутое в общем виде, создав расширение класса потока, которое устанавливает его имя в виде трассировки стека его вызова создания, а затем используйте это с вашими реализациями Runnable вместо стандартного класса потока Java. (см. ниже), но в дополнение к трассировке стека может быть более специфичная для контекста информация, которая будет полезна в имени потока для отладки (ссылка на одну из множества очередей или сокетов, которые он может обработать, например, в этом случае вы можете предпочесть расширить Thread специально для этого случая, чтобы вы могли заставить компилятор заставить вас (или других пользователей, использующих ваши библиотеки) передавать определенную информацию (например, нужную очередь / сокет) для использования в имени).
Вот пример общего потока с трассировкой вызывающего стека в качестве имени:
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"));
}
}
и вот пример выходных данных, сравнивающих два имени:
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]