クラスのコンストラクター内でスレッドの開始メソッドを呼び出すべきではない理由について、私は正当性を探してきました。次のコードを検討してください。
class SomeClass
{
public ImportantData data = null;
public Thread t = null;
public SomeClass(ImportantData d)
{
t = new MyOperationThread();
// t.start(); // Footnote 1
data = d;
t.start(); // Footnote 2
}
}
ImportantData は一般的なもの (おそらく重要) のボックスであり、MyOperationThread は SomeClass インスタンスの処理方法を知っているスレッドのサブクラスです。
フットノード:
これが安全でない理由を完全に理解しています。MyOperationThread が、次のステートメントが終了する前 (およびデータが初期化される前) に SomeClass.data にアクセスしようとすると、準備ができていなかった例外が発生します。または多分私はしません。スレッドで常に判断できるとは限りません。いずれにせよ、私は後で奇妙で予期しない動作に備えています。
なぜこのようにすることが禁断の領域なのか理解できません。この時点で、SomeClass のすべてのメンバーが初期化され、状態を変更する他のメンバー関数は呼び出されていないため、構築は効果的に終了します。
私が理解していることから、これを行うことが悪い習慣と見なされる理由は、「まだ完全に構築されていないオブジェクトへの参照をリークする」可能性があるためです。しかし、オブジェクトは完全に構築されており、コンストラクターは戻る以外に何もすることがありません。この質問に対するより具体的な回答を探して他の質問を検索し、参照資料も調べましたが、「これほどの望ましくない動作のためにすべきではない」というものは見つかりませんでした。あなたはすべきではありません。
コンストラクターでスレッドを開始することは、この状況と概念的にどのように異なるでしょうか。
class SomeClass
{
public ImportantData data = null;
public SomeClass(ImportantData d)
{
// OtherClass.someExternalOperation(this); // Not a good idea
data = d;
OtherClass.someExternalOperation(this); // Usually accepted as OK
}
}
余談ですが、クラスがファイナルだったらどうしますか?
final class SomeClass // like this
{
...
これについて多くの質問と、すべきではないという回答を見ましたが、説明を提供するものはなかったので、もう少し詳細な質問を追加しようと思いました.