你知道被中断的线程,运行状态发生了什么变化吗?

今天我们来一起聊一个问题: “被中断的线程,运行状态发生了什么变化”
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--");

    }

}

如上代码运行情况如下图所示:
你知道被中断的线程,运行状态发生了什么变化吗?_第1张图片如上代码创建了一个子线程启动,子线程间隔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--");

    }

}

如上代码运行情况如下图所示:
你知道被中断的线程,运行状态发生了什么变化吗?_第2张图片
以上代码中,子线程调用了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");
            }
        });

你可能感兴趣的:(Java,Java面试经典题目剖析)