3

スレッドの割り込みと、停止を呼び出さずにスレッドを終了させる方法を学習しようとしています。

public class Test implements Runnable{
        static Thread threadTest=null;
        public static void main(String args[]){
          System.out.println("Hello i am main thread");
          Test thread= new Test();
          threadTest= new Thread(thread);
          threadTest.start();   
}

private static void exitThread() {
    threadTest.interrupt();
}

 @Override
 public void run() {
    boolean run = true;
    while (run) {
        try {
            System.out.println("Sleeping");
            Thread.sleep((long) 10000);
            exitThread();
            System.out.println("Processing");

        } catch (InterruptedException e) {

            run = false;
        }
    }

}


}

出力

Hello i am main thread

Sleeping

Processing

Sleeping

Sleeping が 2 回目に出力され、中断された例外が 1 回目ではなく 2 回目にスローされる理由を理解できません。java でスレッドを停止するために volatile キーワードが使用されている投稿を確認しましたが、それがどのように使用されるのか理解できません。このシナリオでは、スレッドが割り込みで停止するためです。

4

3 に答える 3

3

sleep メソッドに 2 回入るのではなく、スレッドが中断されていることを確認するには、run メソッドの while ループ テストを変更して、割り込みフラグをチェックします。

@Override
 public void run() {
    while (!Thread.currentThread().isInterrupted()) {
        try {
            System.out.println("Sleeping");
            Thread.sleep((long) 10000);
            exitThread();
            System.out.println("Processing");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

スレッドはスリープ状態になり、独自の割り込みフラグを設定し、フラグをチェックして終了します。InterruptedException は、割り込みフラグが設定されている間にスレッドがスリープしていた場合にのみ、Thread#sleep メソッドによってスローされます。

ローカルのブール変数は必要ありません。Thread#sleep が InterruptedException をスローした場合 (この例では、スレッドが中断フラグをチェックして while ループを終了するため、スローされません)、割り込みフラグがクリアされ、catch ブロックでそれを復元することで、while テストで例外が発生したことを確認できます。スレッドが中断されました。

実際のプログラムでは、スレッドは別のスレッドから割り込まれますが、スレッドが自分自身を割り込む理由はありません (代わりに戻ることができます)。

于 2015-08-11T15:25:30.123 に答える
1

ここでは、別のスレッドTest クラスを作成していますが、 「メイン」には独自のスレッドがあるため、作成した新しいスレッドは解釈されます。ここで、このコードでは、メインスレッドではなく、新しく作成されたスレッドThread-0を中断しています。このコードを実行すると、メソッドexitThread()に入る前にスレッドがスリープ状態になるため、処理が表示されますが、exitthread()に入った後にスレッドをスリープ状態にすると、次のコードのように答えが得られます。

public class Test は Runnable を実装します { public boolean run = true;

@Override
public void run() {
    while (run) {

        try {
            System.out.println("Sleeping...");
            exitThread();
            Thread.sleep(10000);
            System.out.println("Processing...");
        } catch (InterruptedException e) {
            System.out.println("Thread intreputted " + e);
            run = false;
        }
    }
}

private void exitThread() {
    Thread.currentThread().interrupt();
    if (Thread.currentThread().isInterrupted())
        System.out.println(Thread.currentThread().getName()
                + " is intreputted");
    else
        System.out.println("alive");
}

public static void main(String[] args) {
    System.out.println("hi I am current thread------>"
            + Thread.currentThread().getName());
    Test test = new Test();
    Thread thread = new Thread(test);
    thread.start();
}

}

それが役立つことを願っています

于 2015-09-04T17:37:00.367 に答える
1

Thread.interrupt() を呼び出すと、スレッドのフラグが設定されるだけです。他には何もしません。ブロッキング メソッド (通常はスロー InterruptedException を宣言するメソッド) のみが、設定されているフラグに (スローによって) 応答します。フラグは、クリアされるまで設定されたままになるという点でスティッキーです。

したがって、sleep メソッドへの最初の呼び出しは正常に実行されます (中断フラグはまだ設定されていません)。その後、スリープ呼び出しが中断されたステータスを検出して例外をスローする 2 番目のループ反復まで、コードは中断されたステータスに作用することは何もしません。

Thread.interrupted() または Thread.isInterrupted() を使用して、いつでも中断ステータスを確認できます (interrupted() が設定されている場合は、中断ステータスもクリアすることに注意してください)。

于 2015-08-08T15:51:50.413 に答える