ここにいる誰もが、Runnable の実装が進むべき道であると考えているようで、私は彼らにまったく同意しませんが、私の意見では Thread を拡張するケースもあります。実際、コードでそれを実証しています。
Runnable を実装する場合、Runnable を実装するクラスはスレッド名を制御できません。次のように、スレッド名を設定できるのは呼び出しコードです。
new Thread(myRunnable,"WhateverNameiFeelLike");
ただし、Thread を拡張すると、クラス自体の中でこれを管理できます (例のように、スレッドに「ThreadB」という名前を付けます)。この場合、次のことを行います。
A)デバッグ目的でより便利な名前を付ける可能性があります
B)その名前がそのクラスのすべてのインスタンスに使用されることを強制しています(それがスレッドであるという事実を無視し、Runnableであるかのように上記を実行しない限り、ここで慣習について話しているので、いずれにしてもそうすることができます私が感じるその可能性を無視してください)。
たとえば、その作成のスタック トレースを取得し、それをスレッド名として使用することもできます。これは奇妙に思えるかもしれませんが、コードの構造によっては、デバッグ目的で非常に役立つ場合があります。
これは小さなことのように思えるかもしれませんが、多くのスレッドを含む非常に複雑なアプリケーションがあり、すべてが突然「停止」した場合 (デッドロックの理由か、ネットワーク プロトコルの欠陥が原因である可能性があります)。明白な - または他の無限の理由) すべてのスレッドが 'Thread-1'、'Thread-2'、'Thread-3' と呼ばれる Java からスタック ダンプを取得することは、常に非常に役立つとは限りません (スレッドの状態によって異なります)。構造化されており、スタックトレースだけでどれがどれであるかを便利に判断できるかどうか-同じコードをすべて実行している複数のスレッドのグループを使用している場合は常に可能であるとは限りません)。
もちろん、その名前をその作成呼び出しのスタックトレースに設定するスレッドクラスの拡張を作成し、それを標準の Java Thread クラスの代わりに Runnable 実装で使用することにより、上記を一般的な方法で行うこともできます。 (以下を参照)しかし、スタックトレースに加えて、デバッグ用のスレッド名に役立つコンテキスト固有の情報がさらにある可能性があります(たとえば、処理できる多くのキューまたはソケットの1つへの参照。その場合に特にスレッドを拡張して、名前で使用するために特定の情報(たとえば、問題のキュー/ソケット)を渡すようにコンパイラーに強制させることができます)。
呼び出し元のスタック トレースを名前として持つ汎用スレッドの例を次に示します。
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"));
}
}
2 つの名前を比較した出力のサンプルを次に示します。
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]