有些初学者对中断的概念可能会有些许小误会,比如线程调用Thread.interrupt()方法,就认为线程会被中断,停止执行,其实不是这样的,让我们来看下中断interrupt详解。
一、interrupt方法
源码如下:
public void interrupt() { //判断是否操作线程
if (this != Thread.currentThread())
checkAccess(); synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) { //只是设置中断标记位
interrupt0(); // Just to set the interrupt flag
b.interrupt(this);
return;
}
}
interrupt0();
}
可以看到interrupt方法并不会对任务终止线程的操作,仅仅只是设置了一个中断的标记位。为了不造成误解,我们看以下示例:
public class InterruptTest {
public static void main(String[] args) {
new test().start();
}
}
class test extends Thread {
static int n = 10;
public void run() {
for (int i = 0; i < 15; i++) {
if (i == n) {
System.out.println("线程要被中断了:" + i);
this.interrupt();
}
System.out.println("当前运行数字为:" + i);
}
}
}
如果interrupt方法会直接终止线程的话,那么当上述代码中的i为10时,后面就不会再继续执行下去了,运行结果为:
可以看到线程还是运行到了最后。正如源码中所说的那样,调用interrupt仅仅只是做了一个中断标识而已,其余并不会做任何操作。
但是也不能说interrupt方法是完全没有任何作用的,因为interrupt方法对于java来说其实是一个协作机制,调用interrupt方法会把调用线程的中断状态设置为true,而其他需要依赖这个中断符的方法在运行时如果监测到这个中断标志就会作出响应。
下面示例,使用Thread.sleep方法观察运行结果。
public class InterruptTest {
public static void main(String[] args) {
new test().start();
}
}
class test extends Thread {
static int n = 10;
public void run() {
for (int i = 0; i < 15; i++) {
if (i == n) {
System.out.println("线程要被中断了:" + i);
this.interrupt();
System.out.println("线程调用中断方法:" + i);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
System.out.println("当前运行数字为:" + i);
}
}
}
运行结果:
上述运行过程中每一次循环都会调用Thread.sleep方法,将线程休眠1秒钟,然而当第10次循环,调用interrupt方法后再调用休眠方法则抛出了异常。
这样的情况在Object.wait等方法中也会出现。所以interrupt相当于java的一个协作机制,如果调用了Object.wait或Thread.sleep方法,会判断线程的中断标志位,如果发现他被设置为true后(线程可以调用interrupt方法来修改标志位),则会抛出异常,后续如果线程不想继续被操作,可以利用这个异常来让线程运行退出,比如for循环的break,或者直接return。
二、isInterrupted方法
public boolean isInterrupted() {
return isInterrupted(false);
}
private native boolean isInterrupted(boolean ClearInterrupted);
检测线程是否中断方法,如果当前线程已经中断则返回true,否则返回false。继续使用上述例子,观察结果:
public class InterruptTest {
public static void main(String[] args) {
new test().start();
}
}
class test extends Thread {
static int n = 10;
public void run() {
for (int i = 0; i < 15; i++) {
if (i == n) {
System.out.println("线程要被中断了:" + i);
this.interrupt();
System.out.println("线程调用中断方法:" + i);
boolean flag = this.isInterrupted();
System.out.println("线程是否被中断:" + flag);
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
System.out.println("当前运行数字为:" + i);
}
}
}
运行结果:
结果发现,线程是否被中断检测方法返回了true。
三、interrupted方法
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
interrupted方法是线程类中的静态方法,在api文档中的说明为返回并清除中断状态。
使用上述例子并将isInterrupted方法替换为interrupted方法。观察结果:
public class InterruptTest {
public static void main(String[] args) {
new test().start();
}
}
class test extends Thread {
static int n = 10;
public void run() {
for (int i = 0; i < 15; i++) {
if (i == n) {
System.out.println("线程要被中断了:" + i);
this.interrupt();
System.out.println("线程调用中断方法:" + i);
boolean flag = Thread.interrupted();
System.out.println("线程是否被中断:" + flag);
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
System.out.println("当前运行数字为:" + i);
}
}
}
运行结果:
上述结果发现,线程在调用Thread.sleep后并没有被中断。加入isInterrupted方法观察线程中断标志位情况:
运行结果说明调用中断方法后调用Thread.sleep方法,没有中断的原因是因为调用了interrupted方法,将中断标志位重置为了false。而interrupted方法返回了true是因为,在重置之前,他的中断标志位是正常的。
四、总结
上述测试和分析了以后对这三个方法应该就比较清晰了。
(1)interrupt方法其实是修改中断标记位为true,起到一个协助的作用,但是并不会真正的终止线程。
(2)isInterrupted方法最纯粹,就是判断当前线程是否有中断标记位,返回结果为true或false。
(3)interrupted方法是一个静态方法,返回的是调用方法前的中断标记位,并清除中断标记位为false。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有