Threadでのinterruptの使い方

3530 ワード

合理的な割り込みスレッド
合理的な中断Threadクラスでは、stop()suspend()およびresume()メソッドが提供されています.この3つのメソッドは、それぞれ終了、一時停止、スレッドの復元に使用されます.しかし、@Deprescatedとマークされて廃棄されています.1つのスレッドは他のスレッドで終了するべきではありません.彼は他の人の通知を受け取るべきで、それから自分が適切な位置で終了し、不合理な終了であれば、臨界領域がまだ完全に操作されていない、ロックを早期に解除しているが、一部の状態が変化している、クリーンアップ操作が行われていないなど、多くの意外な結果をもたらす.
以上の理由により、Javaは新しい割り込みメカニズム(interrupt)を提供し、他のスレッドはスレッドを終了したいinterrupt()メソッドを呼び出します.このとき、スレッドは自分の状態に応じて応答します.
  • スレッドがブロック状態(sleep,wait,join)の場合、スレッドが放出されるInterruptedException異常
  • スレッドが正常に動作している場合は正常に動作するが、中断したフラグはtrueに設定されており、自分の終了を通知されたことに相当する.
  • 呼び出されたスレッドがブロックされています
    public static void main(String[] args) {
        Thread thread = new Thread() {
            @Override
            public void run() {
                try {
                    //         30s
                    sleep(30000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        try {
            //     
            thread.start();
            //        3 
            TimeUnit.SECONDS.sleep(3);
            //     
            thread.interrupt();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    // ↓ out ↓
    // java.lang.InterruptedException: sleep interrupted
    // ...

    呼び出されたスレッドは正常に動作しています
    呼び出すスレッドがブロックされていない場合は、フラグを監視するためのメソッドを呼び出す必要がある.
    public static void main(String[] args) {
        Thread thread = new Thread() {
            @Override
            public void run() {
                while (!Thread.interrupted()) {
                    System.out.println("     ...");
                }
            }
        };
        try {
            thread.start();
            TimeUnit.SECONDS.sleep(3);
            thread.interrupt();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    // ↓ out ↓
    //      
    // ...

    このプログラムはinterruptフラグを検出する、interruptフラグがtrueに設定されていることを発見すると、自分自身を終了する.
    interrupted()とisInterrupt()の違い
    違い:interruptフラグをクリアするかどうか.isInterrupt()メソッドはフラグを変更しないが、interrupted()メソッドは検出と同時にフラグがtrueであることが判明するとtrueを返し、フラグをfalseに設定.
    public static void main(String[] args) {
        Thread thread = new Thread() {
            @Override
            public void run() {
                while (!Thread.interrupted()) {
                    System.out.println("     ...");
                }
                // ⚠️⚠️      ⚠️⚠️
                System.out.println(Thread.interrupted());
            }
        };
        try {
            thread.start();
            TimeUnit.SECONDS.sleep(3);
            thread.interrupt();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    // ↓ out ↓
    //      ...
    // ...(  )
    // false

    前述の例では、Thread.interrupted()メソッドは、trueとしてマークする場合にinterruptedのフラグを変更する.
    public static void main(String[] args) {
        Thread thread = new Thread() {
            @Override
            public void run() {
                // ⚠️⚠️    ⚠️⚠️
                while (!isInterrupted()) {
                    System.out.println("     ...");
                }
                System.out.println(Thread.interrupted());
            }
        };
        try {
            thread.start();
            TimeUnit.SECONDS.sleep(3);
            thread.interrupt();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    // ↓ out ↓
    //      ...
    // ...(  )
    // true

    ソース解析
    ソースコードを観察することにより、interruptedメソッドは最後にisInterrupted(true)メソッドを呼び出し、入力パラメータはフラグビットをクリアするかどうかを表す.isInterrupted(boolean)はローカルメソッドであり、最終的にはC/C++で実行される.isInterrupted()が最後に入力パラメータはfalseであり、フラグビットをクリアしないことを示す.