2008-09-17 10 views
10

スレッドが独自のコンストラクタ内でthis.start()を呼び出すことは正当ですか?もしあれば、これによって起こりうる潜在的な問題は何か?コンストラクタが完了するまでオブジェクトが完全に初期化されていないことを理解していますが、これ以外にも問題はありますか?独自のコンストラクタ内でthread.start()を呼び出す

答えて

1

これは合法ですが、賢明ではありません。インスタンスのスレッド部分は完全に初期化されますが、コンストラクタは初期化されません。スレッドを拡張する理由はほとんどなく、このような手口を引き出すことはあなたのコードを助けるものではありません。

2

私はあなたのコードをあまり冗長にしたくないと思います。代わりに、あなただけの

activeThreads.add(new CustomThread()); 

を言うことができ

Thread t = new CustomThread(); 
t.start(); 
activeThreads.add(t); 

を言って、私はまた、より少ない冗長性を持っているような、私はあなたがこれを行うべきではない、他の回答に同意します。具体的には、それは規約を破る。 2番目の例を読んでいるJavaに精通している人は、スレッドが開始されていないと仮定します。さらに悪いことに、あなたと何らかの形で相互作用する独自のスレッドコードを書くと、スレッドによってはstartを呼び出す必要があり、他のスレッドは呼び出されません。

自分で作業しているときにはこれは魅力的ではないかもしれませんが、最終的には他の人とやりとりする必要があります。他の人と一緒に仕事をしたり、標準的な規則で書かれたコード

しかし、慣習を気にかけず、特別な冗長さを嫌うならば、先に進んでください。誤ってstartに複数回電話をかけようとしても、問題はありません。 1は、下の冗長性を望んでいるし、まだその「標準」の意味で、コンストラクタを続けるならば、1はファクトリメソッドを作成することができところで

2

、:

activeThreads.add(CustomThread.newStartedThread()); 
+0

これはOPの質問とどのように関連していますか? – subsub

1

それはは「法的」ですが、私は考えます最も重要な問題は次のとおりです。 クラスは1つのことを行い、それをうまくやる必要があります。

クラスがスレッドを内部的に使用する場合は、そのスレッドの存在をパブリックAPIで表示しないでください。これにより、パブリックAPIに影響を与えずに改善が可能です。解決策:ThreadではなくRunnableを拡張します。

このクラスではスレッドで実行される一般的な機能を提供するクラスの場合は、に常ににスレッドを作成することを制限したくありません。ここで同じ解決策:スレッドではなく、Runnableを拡張する。

あまり冗長ではないため、ファクトリメソッド(Foo.createAndRunInThread()など)を使用することをおすすめします。

13

メモリの安全性の理由から、オブジェクトまたはそのオブジェクトのフィールドへの参照を、そのコンストラクタ内の別のスレッドに公開しないでください。カスタムスレッドにインスタンス変数があると仮定すると、コンストラクタ内からインスタンス変数を開始することによって、Javaメモリモデルのガイドラインに違反することが保証されます。詳細はBrian Goetz's Safe Construction Techniquesを参照してください。

+1

この回答にコメントしますか?間違っているわけではありません。 –

+1

Downvote?これが間違っていると思われる場合は、サイトをソースしてください。これは正しいです。 –

+0

答えはまったくできません。 Runnableコンストラクタを使用しない限り、コンストラクタが完了する前に 'Thread#run'の中から' this'を参照することができます。これはメモリ安全ルールに違反します。したがって、あなたは注意する必要があります。 –

3

さらに、スレッドクラスがさらにサブクラス化されている場合には、厄介な問題が発生します。その場合、super()が終了すると既にスレッドが実行されてしまい、そのサブクラスがそのコンストラクタで行うことができるものが無効になる可能性があります。

@bill barksdale スレッドがすでに実行されている場合、startを再度呼び出すと、IllegalThreadStateExceptionが発生します.2つのスレッドがありません。

1

法律...はい(他のところで言及されているように注意してください)。お勧めです...いいえ。

私はちょうどあなたがあまりにも簡単に避けることができる匂いです。あなたのスレッドを自動起動させたい場合は、Heinz Kabutzのようにしてください。

public class ThreadCreationTest { 
    public static void main(String[] args) throws InterruptedException { 
    final AtomicInteger threads_created = new AtomicInteger(0); 
    while (true) { 
     final CountDownLatch latch = new CountDownLatch(1); 
     new Thread() { 
     { start(); } // <--- Like this ... sweet and simple. 
     public void run() { 
      latch.countDown(); 
      synchronized (this) { 
      System.out.println("threads created: " + 
       threads_created.incrementAndGet()); 
      try { 
       wait(); 
      } catch (InterruptedException e) { 
       Thread.currentThread().interrupt(); 
      } 
      } 
     } 
     }; 
     latch.await(); 
    } 
    } 
} 
関連する問題