web-dev-qa-db-ja.com

同じスレッドでstartメソッドを2回呼び出すことは合法ですか?

次のコードは、プログラムでstart() method second timeを呼び出したときに_Java.lang.IllegalThreadStateException: Thread already started_になります。

_updateUI.join();    

if (!updateUI.isAlive()) 
    updateUI.start();
_

これは、second time updateUI.start()が呼び出されたときに発生します。私はそれを複数回実行し、スレッドが呼び出され、updateUI.start()を押す前に完全に実行されます。

updateUI.run()を呼び出すと、エラーは回避されますが、スレッドはUIスレッド(SOの他の投稿で述べたように、呼び出しスレッド)で実行されます。

スレッドは一度だけstartedできますか?もしそうなら、スレッドを再度実行したい場合はどうすればよいですか?この特定のスレッドは、UIスレッドで実行するよりもスレッドで実行せず、ユーザーが不当に長い待機をしている場合、バックグラウンドで計算を実行しています。

88
Will

Java API Specification から Thread.start メソッド:

スレッドを複数回開始することは決して合法ではありません。特に、スレッドは実行が完了すると再起動されない場合があります。

さらに:

スロー:
IllegalThreadStateException -スレッドがすでに開始されている場合。

そのため、Threadは一度しか開始できません。

もしそうなら、スレッドを再度実行したい場合はどうすればよいですか?

Threadを複数回実行する必要がある場合は、Threadの新しいインスタンスを作成し、startを呼び出す必要があります。

109
coobird

その通りです。 ドキュメントから

スレッドを複数回開始することは決して合法ではありません。特に、スレッドは実行が完了すると再起動されない場合があります。

繰り返し計算のためにできることに関しては、 SwingUtilities invokeLater method を使用できるかのようです。すでにrun()を直接呼び出して実験しています。つまり、生のRunnableではなくThreadを使用することをすでに考えています。 invokeLaterタスクだけでRunnableメソッドを使用してみて、それがあなたのメンタルパターンに少し合っているかどうかを確認してください。

ドキュメントの例を次に示します。

_ Runnable doHelloWorld = new Runnable() {
     public void run() {
         // Put your UI update computations in here.
         // BTW - remember to restrict Swing calls to the AWT Event thread.
         System.out.println("Hello World on " + Thread.currentThread());
     }
 };

 SwingUtilities.invokeLater(doHelloWorld);
 System.out.println("This might well be displayed before the other message.");
_

そのprintln呼び出しを計算に置き換えると、まさに必要なものになるかもしれません。

編集:コメントをフォローアップしても、元の投稿でAndroidタグに気付きませんでした。Android workのinvokeLaterに相当するものはHandler.post(Runnable)。javadocから:

_/**
 * Causes the Runnable r to be added to the message queue.
 * The runnable will be run on the thread to which this handler is
 * attached.
 *
 * @param r The Runnable that will be executed.
 *
 * @return Returns true if the Runnable was successfully placed in to the
 *         message queue.  Returns false on failure, usually because the
 *         looper processing the message queue is exiting.
 */
_

したがって、Androidの世界では、上記と同じ例を使用して、_Swingutilities.invokeLater_をHandlerへの適切な投稿に置き換えることができます。

13
Bob Cross

いいえ、スレッドを再び起動することはできません。そうすると、runtimeException Java.lang.IllegalThreadStateExceptionがスローされます。 >

その理由は、run()メソッドがスレッドによって実行されると、デッド状態になるためです。

例を見てみましょう-スレッドを再び開始し、そのスレッドで内部的にrun()メソッドを呼び出すstart()メソッドを呼び出すことを考えると、デッドマンに目を覚まして実行するように依頼するようなものです。として、彼の人生を完了した後、人は死んだ状態になります。

public class MyClass implements Runnable{

    @Override
    public void run() {
           System.out.println("in run() method, method completed.");
    }

    public static void main(String[] args) {
                  MyClass obj=new MyClass();            
        Thread thread1=new Thread(obj,"Thread-1");
        thread1.start();
        thread1.start(); //will throw Java.lang.IllegalThreadStateException at runtime
    }

}

/ * run()メソッドのOUTPUT、メソッドが完了しました。スレッド「メイン」の例外Java.lang.Thread.start(Unknown Source)でのJava.lang.IllegalThreadStateException * /

チェックしてください

3
Sameer Kazi

到着したばかりの答えは、あなたがしていることをしてはいけない理由をカバーしています。実際の問題を解決するためのいくつかのオプションがあります。

この特定のスレッドは、UIスレッドで実行するよりもスレッドで実行せず、ユーザーが不当に長い待機をしている場合、バックグラウンドで計算を実行しています。

独自のスレッドをダンプし、AsyncTaskを使用します。

または、必要なときに新しいスレッドを作成します。

または、スレッドを再起動するのではなく、作業キュー(たとえば、LinkedBlockingQueue)から操作するようにスレッドを設定します。

3
CommonsWare

Runnableを作成し、Runnableを実行するたびに新しいスレッドでラップする必要があります。本当にいですが、別のスレッドでスレッドをラップしてコードを再度実行することはできますが、これを行うのは本当に必要なことです。

2
Peter Lawrey

あなたが言ったように、スレッドは複数回起動することはできません。

馬の口からまっすぐ: Java API仕様

スレッドを複数回開始することは決して合法ではありません。特に、スレッドは実行が完了すると再起動されない場合があります。

スレッドで行われていることをすべて再実行する必要がある場合は、新しいスレッドを作成して実行する必要があります。

1
alanlcode

はい、すでに実行中のスレッドを開始することはできません。実行時にIllegalThreadStateExceptionをスローします-スレッドがすでに開始されている場合。

本当にスレッドを開始する必要がある場合:オプション1)スレッドを複数回実行する必要がある場合、スレッドの新しいインスタンスを作成し、そのスレッドでstartを呼び出す必要があります。

0
riteeka

Java APIでスレッドを再利用することは違法です。ただし、実行可能な実装にラップして、そのインスタンスを再実行できます。

0
Aaron He

スレッドは一度だけ開始できますか?

はい。一度だけ開始できます。

スレッドを再度実行したい場合はどうすればいいですか?この特定のスレッドは、UIスレッドで行うよりもスレッドでそれを行わず、ユーザーが不合理に持っている場合、バックグラウンドで何らかの計算を行っています長い待ち時間。

Threadを再度実行しないでください。代わりに Runnable を作成し、 Handler of HandlerThread に投稿します。複数のRunnableオブジェクトを送信できます。 Runnablerun()メソッドを使用してUIスレッドにデータを送り返す場合は、UIスレッドのMessageHandlerをポストし、handleMessageを処理します。

サンプルコードについては、この投稿を参照してください。

Android:スレッドでトースト

0
Ravindra babu