この記事では、java に関する関連知識を提供します。主にスレッドの中断に関する関連内容を紹介します。中断とは、スレッドが互いに中断する方法です。たとえば、スレッド a とスレッド b が 2 つあります。 a がある時点で b の実行を中断したい場合、 b.interrupt() メソッドを呼び出して中断することができます。一緒に見てみましょう。皆さんのお役に立てれば幸いです。
推奨学習: 「java ビデオ チュートリアル 」
Java マルチスレッド プログラミングの interrupt()
メソッド、isInterrupted()
メソッド、および interrupted()
メソッドはすべて、スレッド 割り込み関連のメソッドは非常に重要です。これら 3 つの方法は名前が非常に似ており、原理を理解していないと混同しやすいため、区別するためにここで紹介します。 interrupt()
メソッドと isInterrupted()
メソッドはどちらもインスタンス メソッド (非クラス静的メソッド) であるため、先頭に thread1
を追加しました。インスタンス化された特定のスレッド:
thread1.interrupt()
メソッドは、スレッドを中断するために使用されます。この割り込みは、通常、割り込み
として理解できます。たとえば、2 つのスレッド a
と b
があり、スレッド a
が何らかの理由でスレッド b
を中断したい場合、スレッド a
b.interrupt()
は内部的に呼び出すことができます。ただし、この実装はスレッド b
の 割り込みステータス フラグ
を設定することで実現されることに注意してください。 b
スレッドコードの実行中、ループ本体内で 割り込みステータスマーク
を継続的に判定することで、a
の割り込み要求が実際に応答したかどうかを確認できます (実行の終了など)。
thread1.isInterrupted()
メソッドは、スレッドの割り込みステータスを取得するために使用されます。たとえば、2 つのスレッド a
と b
があり、スレッド a
が何らかの理由でスレッド b
を中断したい場合は、b を使用できます。 .interrupt()
b
に割り込みます。スレッド b
内では、その割り込みステータスと割り込みがあったかどうかを確認し、割り込みステータスに基づいて割り込み要求に応答するかどうか (現在のスレッドのループ本体の終了など) を確認できます。 )。 thread1.isInterrupted()
native
メソッドはメソッド内で直接呼び出されます。受信した ClearInterrupted
パラメータは false
です。割り込みステータスはクリアされません マーク:
public boolean isInterrupted() { return isInterrupted(false); }// ClearInterrupted表示是否清楚中断状态标记private native boolean isInterrupted(boolean ClearInterrupted);
したがって、このメソッドを呼び出した後、割り込みフラグはクリアされません。
Thread.interrupted()
は、Thread
クラスで定義された静的メソッドです。は、現在の スレッドの割り込みステータス を決定するために使用されます。thread1.isInterrupted()
とは異なり、このメソッドは、割り込みに戻った後、(リセット) をリセットします。割り込みステータス マーク、いわゆるリセットはデフォルト状態に戻すことであり、これは割り込みステータス マークをクリアするとも言えます。 Thread クラスのソース コードを見ると、
Thread.interrupted() メソッドの実装が非常に簡単であることがわかります。
native メソッドは内部で直接呼び出されます。ただし、
ClearInterrupted渡されたパラメータは
true で、これは割り込みステータス マークをクリアすることを意味します:
public static boolean interrupted() { return currentThread().isInterrupted(true); }// ClearInterrupted表示是否清楚中断状态标记private native boolean isInterrupted(boolean ClearInterrupted);
thread1 であることがわかります。 isInterrupted() と
Thread.interrupted () の違いは、実際には、割り込みステータス フラグを取得した後にリセットするかどうかにあります。ニーズに合わせてご利用いただけます。
a と
b があります。スレッド
a がスレッド
b に割り込みたい場合、
b.interrupt( )スレッド
b の割り込みマークを設定して、スレッド
b に通知するメソッド。スレッド
b は、次の実装のように、いつでも他のスレッドからの割り込みに応答できるように、自身の割り込みマークを常にチェックする必要があります:
public class TestMain { public static void main(String[] args) throws InterruptedException { Thread b = new Thread(new Runnable() { @Override public void run() { int num = 0; while(true) { if (Thread.interrupted()) { break; } System.out.println("thread b running, num is:" + num++); } } }); b.start(); // 主线程sleep 1ms,让线程b循环一小会 Thread.sleep(1); // 中断线程b b.interrupt(); } }これは
メイン スレッド#内にあります。 ## 新しいスレッド b
が作成されます。スレッド b
の内部がループ本体です。各ループの開始時に、割り込みステータスがチェックされ、割り込みが発生しているかどうかが確認されます。中断された場合は、ループを終了してスレッドを終了します。メインスレッドは 1ms スリープし、最初にスレッド b を数回ループさせます。次に、メインスレッドは b.interrupt()
を通じてスレッド b
を中断します。プログラムを実行すると、次の出力が表示されます (結果はマシンによって異なります)。
thread b running, num is:0thread b running, num is:1thread b running, num is:2... thread b running, num is:25thread b running, num is:26thread b running, num is:27Process finished with exit code 0
可以看到主线程成功的中断了线程b
。当然,主线程之所以能成功的中断线程b
,是因为线程b
一直在检查自己的中断状态(如果线程b
太自我,不考虑其他线程,只考虑自己运行,那主线程就无法成功打断线程b
了)。
前面我们成功的在主线程中中断了线程b
,然后如果线程b
中存在阻塞,比如下面的代码所示,线程b
在sleep时被主线程中断:
public class TestMain { public static void main(String[] args) throws InterruptedException { Thread b = new Thread(new Runnable() { @Override public void run() { int num = 0; while(true) { if (Thread.interrupted()) { break; } try { Thread.sleep(1000); } catch (InterruptedException e) { // Thread.currentThread().interrupt(); e.printStackTrace(); } System.out.println("thread b running, num is:" + num++); } } }); b.start(); // 主线程sleep5.5秒,让线程b循环5次 Thread.sleep(5500); // 中断线程b b.interrupt(); } }
这时线程b
会抛出InterruptedException
异常,上面的代码中我们仅仅打印了下该异常,相当于什么都没做。运行该代码结果如下:
thread b running, num is:0thread b running, num is:1thread b running, num is:2thread b running, num is:3thread b running, num is:4java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at test.TestMain$1.run(TestMain.java:25) at java.lang.Thread.run(Thread.java:748) thread b running, num is:5thread b running, num is:6thread b running, num is:7thread b running, num is:8thread b running, num is:9...
可以看出,主线程未能成功中断线程b
。
线程内调用wait
,join
,sleep
时都会进入阻塞状态。当线程处于阻塞状态时被中断,这时线程就会抛出InterruptedException
异常,其实大家可以通俗的理解为一种通知即可。以sleep
方法为例,大家可以按如下模拟实现来理解(底层是native实现):
public static void sleep(long millis) throws InterruptedException { while (/* still waiting for millis to become zero */) { if (Thread.interrupted()) { throw new InterruptedException(); } // Keep waiting } }
有了InterruptedException
异常通知,线程就可以在阻塞时立即知道被中断了,进而采取一定的措施响应中断。需要注意的一点是,由于抛出了InterruptedException
异常,因此不会在设置中断标志位。
理解了InterruptedException
异常,我们就可以在线程即使发生阻塞时也能成功进行中断了,如下所示:
public class TestMain { public static void main(String[] args) throws InterruptedException { Thread b = new Thread(new Runnable() { @Override public void run() { int num = 0; while(true) { if (Thread.interrupted()) { break; } try { Thread.sleep(1000); // 用sleep来模拟线程的执行 } catch (InterruptedException e) { Thread.currentThread().interrupt(); // 注意这里是重点! } System.out.println("thread b running, num is:" + num++); } } }); b.start(); // 主线程sleep5.5秒,让线程b先循环5次 Thread.sleep(5500); // 中断线程b b.interrupt(); } }
这里我们在检查到InterruptedException
异常时,重新设置了中断标志位,这样下次循环一开始时,即可判断被中断了,进而退出循环体。当然我们可以在InterruptedException
异常catch
时直接退出。
我们介绍了Java中的线程中断相关知识点,通俗来讲,大家可以理解为中断就是一种线程间相互打断的一种方式,比如两个线程a
和b
,a
如果在某一时刻想打断b
的执行,则可以调用b.interrupt()
方法进行中断,但是要注意,这里仅仅是设置b
的中断状态位,b
看到中断状态位后可以自行决定是否响应,当然,正常情况我们写的代码都需要做好中断状态位的判断(这一点大家在写业务代码时确实经常忽略)。另外对于阻塞中的线程,Java通过InterruptedException
异常来进行通知。
推荐学习:《java视频教程》
以上がJava でのスレッド中断の詳細な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。