你知道被中断的线程,运行状态发生了什么变化吗?
今天我们来一起聊一个问题: “被中断的线程,运行状态发生了什么变化”
Java中的中断并不是说会把正在运行的线程终止,而是仅仅设置下线程的中断标志,列如下面的代码:
package JavaDemo;
/**
* @program: JavaDemo
* @description:
* @author: 码上Java
* @create: 2019-05-25 16:39
*/
public class Main {
private static final String THREAD_NUM="biz-thread";
public static void main(String[] args) throws InterruptedException {
//创建线程,内部任务是死循环
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
for (;;){
System.out.println("I am a sub thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//不捕获该异常
}
}
}
},THREAD_NUM);
//启动
thread.start();
//用户线程休眠3s
Thread.sleep(3000);
//中断子线程
System.out.println("--begin interrupt sub thread--");
thread.interrupt();
System.out.println("--end interrupt sub thread--");
}
}
如上代码运行情况如下图所示:
如上代码创建了一个子线程启动,子线程间隔1s打印输出,main函数所在线程休眠3s后,调用子线程的interrupt方法中断子线程,可知子线程被中断后继续间隔1s打印一句,这说明设置线程中断标志并不会改变线程的运行状态,更不会打断线程的执行。
Thread类中关于中断的方法有三个:
void interrupt()方法:中断线程,仅仅设置线程的中断标志位true并立即返回,线程的运行状态并不会发生变化。
源码如下:
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();
}
boolean isInterrupted() :检测当前线程是否被中断,如果是返回true,否则返回false。
源码如下:
public boolean isInterrupted() {
//传递false,说明不清除中断标志
return isInterrupted(false);
}
boolean interrupted() :检测当前线程是否被中断,如果是返回true,否则返回false。与isInterrupted不同的是,该方法发现当前线程被中断后会清除中断标志。
源码如下:
private native boolean isInterrupted(boolean ClearInterrupted);
需要注意的是,当一个线程处于休眠的时候,如果其他线程中断了它,则处于休眠的线程会抛出java.lang.InterruptedException异常而返回:
public class Main {
private static final String THREAD_NUM="biz-thread";
public static void main(String[] args) throws InterruptedException {
//创建线程
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
System.out.println("I am a sub thread");
try {
Thread.sleep(10000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("--I am interrupted--");
}
},THREAD_NUM);
//启动
thread.start();
//用户线程休眠3s
Thread.sleep(3000);
//中断子线程
System.out.println("--begin interrupt sub thread--");
thread.interrupt();
System.out.println("--end interrupt sub thread--");
}
}
如上代码运行情况如下图所示:
以上代码中,子线程调用了Thread.shleep(10000000);,表示自己休眠10000s,在没其他线程干扰的情况下,子线程需要等10000s后才会从sleep返回,但是这里main函数所在线程休眠3s后中断了子线程,这时候子线程从sleep处抛出java.lang.InterruptedException异常后返回了。
Java中的线程中断只是简单设置中断标志,至于剩下的事情就需要我们自己来做,比如根据中断标志来判断是否退出执行。
下面看一下线程使用Interrupted优雅退出的经典例子,代码如下:
//创建线程
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
//如果当前线程被中断则退出循环
while (!Thread.currentThread().isInterrupted())
System.out.println(Thread.currentThread()+"Hello");
}
});

查看8道真题和解析