This article brings you relevant knowledge aboutjava, which mainly introduces the relevant content about thread interruption. Interruption is a way for threads to interrupt each other, such as two There are threads a and b. If a wants to interrupt the execution of b at a certain moment, it can call the b.interrupt() method to interrupt. Let's take a look at it together. I hope it will be helpful to everyone.
Recommended study: "java video tutorial"
Theinterrupt()
method,isInterrupted()
method andinterrupted()
method in Java multi-thread programming are all related to threads Interrupt related methods are very important. The names of these three methods are very similar, and it is easy to confuse them if you do not understand the principles. They are introduced here to distinguish them. Since theinterrupt()
method and theisInterrupted()
method are both instance methods (non-class static methods), I added athread1
in front, Represents an instantiated specific thread:
thread1.interrupt()
method is used to interrupt the thread, so-called The interruption can be commonly understood asinterruption
. For example, there are two threadsa
andb
. When threada
wants to interrupt threadb
for some reason, threada
b.interrupt()
can be called internally. However, please note that the implementation is achieved by setting theinterrupt status flag
of the threadb
.b
During the running of the thread code, theinterrupt status mark
can be continuously judged in a loop body to confirm whether the interrupt request ofa
is actually responded to (such as exiting execution, etc. ).
thread1.isInterrupted()
method is used to obtain the interrupt status of a thread. For example, there are two threadsa
andb
. When threada
wants to interrupt threadb
for some reason, you can useb. interrupt()
Interruptsb
. Inside threadb
, you can determine its interrupt status and whether it was interrupted, and then confirm whether to respond to the interrupt request based on the interrupt status (such as exiting the loop body of the current thread, etc.).thread1.isInterrupted()
Thenative
method is directly called inside the method. The incomingClearInterrupted
parameter isfalse
, which means that the interrupt status is not cleared. Mark:
public boolean isInterrupted() { return isInterrupted(false); }// ClearInterrupted表示是否清楚中断状态标记private native boolean isInterrupted(boolean ClearInterrupted);
Therefore, after calling this method, the interrupt flag is not cleared.
Thread.interrupted()
is a static method defined on theThread
class , used to determinethe interruption status of the currentthread. Different fromthread1.isInterrupted()
, this method willreset(reset) after returning to the interruption status. Interrupt status mark, the so-called reset is to restore the default state, which can also be said to clear the interrupt status mark. Looking at theThread
class source code, you can see that theThread.interrupted()
method is very simple to implement. Thenative
method is directly called internally, except thatClearInterrupted
The parameter passed istrue
, which means clearing the interrupt status mark:
public static boolean interrupted() { return currentThread().isInterrupted(true); }// ClearInterrupted表示是否清楚中断状态标记private native boolean isInterrupted(boolean ClearInterrupted);
It can be seen thatthread1.isInterrupted()
andThread.interrupted The difference between ()
actually lies in whether to reset it after obtaining the interrupt status flag. You can choose to use it according to your needs.
If you want to gracefully stop a thread from running, you need the interrupt mechanism introduced earlier. For example, there are two threadsa
andb
. When threada
wants to interrupt threadb
, it can callb.interrupt()
Method to set the interrupt mark of threadb
to notify threadb
. The threadb
needs to constantly check its own interrupt mark to respond to interrupts from other threads at any time, such as the following implementation:
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(); } }
This is within themain thread
A new threadb
is created. The inside of threadb
is a loop body. At the beginning of each loop, the interrupt status is checked to confirm whether it has been interrupted. If it is interrupted, exit the loop and end the thread. execution. The main thread sleeps for 1ms and lets thread b loop several times first. Then the main thread interrupts threadb
throughb.interrupt()
. When you run the program, you can see the following output (the results vary on different machines):
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视频教程》
The above is the detailed content of Detailed introduction to thread interruption in Java. For more information, please follow other related articles on the PHP Chinese website!