Runnable を実装して Thread コンストラクターに渡すことで同じ機能を実現できる場合、ユーザーが Thread クラスを拡張してスレッドを作成できるようにすることの本質は何ですか。
6 に答える
Runnable を実装して同じ機能を実現し、それを Thread コンストラクターに渡す
Thread の拡張の使用は、Runnable に限定されません。たとえば、一部のメソッドの動作を変更したり、独自のスレッド ローカル情報を追加したりできます (常に でアクセスできますThread.currentThread()
)。
Thread
歴史的な観点から、 Java が匿名内部クラスをサポートする前に、API が Java 1.0 で設計されたことを理解する必要があります。また、初期のサンプル コードの多くは、 のサブクラス化を示していますThread
。それは後になってからでした:
- 匿名内部クラス (Java 1.1) のサポートを追加しました。
- 彼らは、
Runnable
インスタンスを提供するために内部クラス(など)を使用する方が良いと考えました - 彼らは、タスク実行、スレッド プールなどの標準クラスを実装しました (Java 5.0)。
「.Net の Thread クラスは final とマークされている」と言うのはすべて非常にうまくいっていますが、C# / .Net が何年も後に登場し、Java の設計から学ぶことができたことを理解する必要があります。Java は、多くの完璧とは言えない設計上の決定という歴史的な荷物に悩まされていました。古いコードを壊さないという最優先事項のためです。
Thread
は、実行するために への参照を取ることができるという点で珍しいですRunnable
が、それ自体もRunnable
です。デフォルトでは、Thread
はそれ自体Runnable
を実行するインスタンスとして使用しますが、もちろん他の場所を指すこともできます。
Thread
final をマークして外部を必要とするRunnable
か、Thread
拡張可能にしてそれを独自のものにする正当な理由ではないと思いますRunnable
。どちらのアプローチもまったく問題なく、どちらが優れているとは思えません。
推測するに、サブクラス化可能にする理由は、次のThread
ようなコードを記述できるようにするためです。
Thread t = new Thread() {
public void run() {
/* ... your code here ... */
}
};
これは、のサブクラスを作成しRunnable
てからスレッドにラップするよりもわずかにクリーンです。同様に、 off をサブクラス化して、それがスレッドとして使用されることになっていることを明確に示すThread
a を取得できます。Runnable
もちろん、これは主に美学の問題であり、Java 設計者がこれとは別の方法で行っていた場合、それは完全に良い決定だったと思います。
スレッド クラスはスレッドの実行方法を記述し、Runnable は何が実行されるかを記述します。実行されるものを変更したい場合は、Runnable を実装する必要があります。スレッドの実行方法を変更したい場合は、Thread から派生します。スレッドの実行方法を変更したい場合は、Thread から派生させて別の Runnable オブジェクトを実装することができます。
何かを追加できる場合は、拡張することで、スレッドがデーモンスレッドとして機能できるようにするなど、スレッドの機能を拡張できます (メソッドのみが含まれているためThread
、存在しません) (ガベージコレクターデーモンスレッドのように)。 . 他のスレッドは、(JVM の起動時に) クラスのメインメソッドを呼び出す単一の非デーモン スレッドのように存在します。Runnable
run()
インターフェイスにより、 (メソッドRunnable
を実装することにより) クラスをスレッドとしてアクティブにすることができますrun()
。
私が考えることができる唯一の良いことは、Thread クラスを拡張すると、run() メソッドを保護されたものとしてマークできるようになることです。Runnable を実装することの欠点の1 つは、run メソッドを public としてマークする必要があることです。