-1

実行順序を予測できるように、以下のコードがデバッガーで実行されると仮定します。

  • t1-ここで、task1はいくつかの長いタスクの作業を開始します。
  • t2 --- task1がロックを保持しているため、task2は@Syncronizedステートメントでブロックされます。
  • t3 --task2は中断されますが、task2が組み込みロックを使用しているため、@同期して中断できないために失敗しました。(Renenterant.lockInterruptible()はInterruptedExecptionをスローします)。
  • t4---task1が中断されます。ただし、try catchブロックで複雑なタスクを実行したにもかかわらず、InterruptedExecptionがスローされることはありませんでした。何故ですか ?

コード:

public class TestInteruptibility {
    public static Object lock = new Object();
    public static boolean spin = true;

    public static void main(String[] args) {
        Thread task1 = new Thread(new Task(), "Task1");
        Thread task2 = new Thread(new Task(), "Task2");
        Thread notifier1 = new Thread(new Notifier(), "Notifier1");
        task1.start();
        task2.start();
        task2.interrupt();
        task1.interrupt();
        notifier1.start();
    }
}

class Task implements Runnable {
    public void run() {
        synchronized (TestInteruptibility.lock) {
            System.out.println("Performing Long Task");
            try {
                while (TestInteruptibility.spin) {
                }
                System.out.println("Finsihed Performing Long Task");
                TestInteruptibility.lock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
                System.out.println("I got interrupted while i was waiting @ wait()");
            }
            System.out.println("Ending Task");
        }
    }
}

class Notifier implements Runnable {
    public void run() {
        synchronized (TestInteruptibility.lock) {
            System.out.println("Performing notification");
            TestInteruptibility.lock.notify();
            System.out.println("Ending notification");
        }
    }
}
4

3 に答える 3

3

基本的には、オブジェクトinterrupt()にフラグを設定することです。Threadで確認する必要がありますisInterrupted()。次に、この割り込み信号を処理できます。InterruptedExceptionこの状況では をスローしません。

Thread.sleep()また、 、などのメソッドがObject.wait()すぐに戻り、InterruptedException. そしてInterruptedException、この状況で取得できます。

Java Concurrency in Practice、7.1.1 より中断:

A good way to think about interruption is that it does not actually interrupt a running thread; it just requests that the thread interrupt itself at the next convenient opportunity. (These opportunities are called cancellation points.) Some methods, such as wait, sleep, and join, take such requests seriously, throwing an exception when they receive an interrupt request or encounter an already set interrupt status upon entry. Well behaved methods may totally ignore such requests so long as they leave the interruption request in place so that calling code can do something with it. Poorly behaved methods swallow the interrupt request, thus denying code further up the call stack the opportunity to act on it.

上記のコードでは、待機/スリープしていません。そのため、ループisInterrupted()内で割り込み信号を自分でチェックして処理する必要があります。while

while (TestInteruptibility.spin) {
    if (Thread.currentThread().isInterrupted()) {
        break;
    }
}

参考文献:

  1. interrupt() が期待どおりに機能しない理由と、それがどのように機能するか
  2. java.lang.Thread.interrupt() は何をしますか?
于 2013-03-17T06:57:45.347 に答える
2

ロックを保持するビジーなwhileループがあります(スピンの値をどこかで変更しない限り、終了することはありません)。task1はまだループに入っていると思いますので、中断に気づきません。Task2はロックを取得できないため、ブロックします。

タスクの実装方法では、ループの後に来る待機コマンド中にのみ中断できます。

ところで:異なるスレッドでスピンデータメンバーを使用している場合は、おそらく揮発性として宣言する必要があります。同様のスレッドセーフ上の理由から、ロックは最終として宣言する必要があります。

于 2013-03-17T06:43:03.103 に答える
0

メソッドを呼び出すとinterrupt()、結果はこのスレッドが現在行っていることによって異なります。などの中断可能なメソッドでブロックされている場合Object.wait()、すぐに中断されInterruptedExceptionます。つまり、スレッド内でスローされます。スレッドがブロックされていないが、いくつかの計算を実行している場合、またはスレッドがスローされず、代わりにスレッドにフラグが設定されてInputStream.read()いるなどの割り込み不可能なメソッドでブロックされている場合。このフラグは、次にスレッドが割り込み可能なメソッドを呼び出すときに発生しますが、今はそうではありません。InterruptedExceptioninterruptedInterruptedException

あなたの場合、スレッドは無限の空のループで回転しているため、割り込み可能なメソッドでブロックされていないため、task1そのスレッド内でnoがスローされますが、フラグは設定されています。おそらく、タスク コードを次のように変更する必要があります。task2interrupt()InterruptedExceptioninterrupted

while (TestInteruptibility.spin && !Thread.interrupted ()) {
}

interrupt誰かがタスクスレッドを呼び出す限り、ループから抜けます。

于 2013-03-17T07:00:05.827 に答える