Thread Interrupt方法

结论

  • Thread.interrupt()方法不会中断一个正在运行的线程,只是设置了中断状态,线程内部可以监听isInterrupted方法响应终止,也可以不处理,继续执行完
  • 如果线程在调用 Object 类的 wait()、wait(long) 或 wait(long, int) 方法,或者该类的 join()、join(long)、join(long, int)、sleep(long) 或 sleep(long, int) 方法过程中受阻,则其中断状态将被清除,它还将收到一个InterruptedException异常。这个时候,我们可以通过捕获InterruptedException异常来终止线程的执行,具体可以通过return等退出或改变共享变量的值使其退出
  • 如果线程是阻塞在io上,对应的资源会被关闭

interrupt相关的API

  • interrupt() : 中断线程方法
  • isInterrupted() : 返回线程是否被中断,中断状态保持不变
  • interrupted() :返回线程是否被中断,但中断状态被清除。换句话说,如果线程被中断后,连续两次调用该方法,则第二次调用将返回 false。

源码

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);      // 中断阻塞的IO/NIO,关闭对应的资源
            return;
        }
    }
    interrupt0();
}

如源码注释所示:interrupt方法主要是设置中断状态,及对应阻塞资源的释放

public boolean isInterrupted() {
    return isInterrupted(false);
}
public static boolean interrupted() {
    return currentThread().isInterrupted(true);
}
private native boolean isInterrupted(boolean ClearInterrupted);

isInterrupted方法和interrupted可以放在一起比较,两个方法都是调用native的isInterrupted方法,两个都是测试线程是否被中断,并将中断状态返回。
不同之处在于:isInterrupted 不会清除中断状态, interrupted会清除中断状态

测试interrupt方法

public class InterruptTest {
    public static int i = 0;
    static int length = 100_000_000_0;
    public static void main(String[] args) throws InterruptedException {
        testNotInterruptIfSubThreadNotCatchInterruptState();
        testWillThrowExceptionWhenSleep();
    }

    private static void testNotInterruptIfSubThreadNotCatchInterruptState() throws InterruptedException {
        Thread t = new Thread(new NormalInterrupt());
        t.start();
        TimeUnit.SECONDS.sleep(1L);
        t.interrupt();
        System.out.println(Thread.currentThread().getName() + ": " + i);
    }

    static class NormalInterrupt implements Runnable {
        @Override
        public void run() {
            //在其他线程中发出中断信号,是否中断还要看线程内部方法怎么写的,没有判断isInterrupted()并不会中断哦
            //可以去掉for循环中的   !Thread.currentThread().isInterrupted()条件
            for(int j = 0; j< length && !Thread.currentThread().isInterrupted(); j++) {
                i = j;
            }
            System.out.println(Thread.currentThread().getName() + ": " + i);
        }
    }

    private static void testWillThrowExceptionWhenSleep() throws InterruptedException {
        Thread t = new Thread(new SleepInterrupt());
        t.start();
        TimeUnit.NANOSECONDS.sleep(1L);
        t.interrupt();
        System.out.println(Thread.currentThread().getName() + ": end");
    }

    static class SleepInterrupt implements Runnable {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + ": start");
            try {
                TimeUnit.SECONDS.sleep(2L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //异常处理后,中断状态将被清除,所以结果是false
            System.out.println(Thread.currentThread().isInterrupted());
            System.out.println(Thread.currentThread().getName() + ": end");
        }
    }
}

运行结果:

main: 922319282
Thread-0: 922319282
Thread-1: start
main: end
java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at java.lang.Thread.sleep(Thread.java:340)
    at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
    at InterruptTest$SleepInterrupt.run(InterruptTest.java:53)
    at java.lang.Thread.run(Thread.java:748)
false
Thread-1: end
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。