Java中interrupt()方法详解附带demo

  Thread.interrupt()的作用是通知线程应该中断了,到底中断还是继续运行,应该由被通知的线程自己处理。当对一个线程,调用 interrupt() 时,

  1.如果线程处于被阻塞状态(例如处于sleep, wait, join 等状态),那么线程将立即退出被阻塞状态,并抛出一个InterruptedException异常。仅此而已。

  2.如果线程处于正常活动状态,那么会将该线程的中断标志设置为 true,仅此而已。被设置中断标志的线程将继续正常运行,不受影响。

  首先说第二条,线程正常执行,通过interrupt()方法将其中断标志设置为true,在线程中使用Thread.interrupted()方法判断当前线程是否被设置中断标志。

public class StopThread implements Runnable {
    public static void main(String[] args) {
        StopThread stopThread = new StopThread();
        Thread thread = new Thread(stopThread);
        thread.start();
        System.out.println("thread starting...");

        try {
            Thread.sleep(3000);
            thread.interrupt();
            System.out.println("interrupt thread!");
            Thread.sleep(3000);
            thread.join();
            System.out.println("main stop!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        int i = 1;
        while (!Thread.interrupted())
            i++;
        System.out.println("i=" + i);
        System.out.println("thread stop!");
    }
} 

  输出:

thread starting...
interrupt thread!
i=-937646695
thread stop!
main stop!

  这里再说一下interrupted(),贴一下jdk1.8源码的方法注释,当调用这个方法会将中断标志重置,如果线程继续执行,下一次调用这个方法返回为false,除非再次调用interrupt()方法设置一次。简单来说就是一次interrupt()只对应一次interrupted()的true状态。

Tests whether the current thread has been interrupted.  The
<i>interrupted status</i> of the thread is cleared by this method.  In
other words, if this method were to be called twice in succession, the
second call would return false 

  接下来研究下第一条,再写一个简单的demo,可以看到线程正在sleep中,调用了interrupt()方法后,直接进入catch (InterruptedException e) {}中,然后继续执行线程后续操作。所以在catch中写停止线程的语句,即可达到目的。

public class StopThread implements Runnable {
    public static void main(String[] args) {
        StopThread stopThread = new StopThread();
        Thread thread = new Thread(stopThread);
        thread.start();
        System.out.println("thread starting...");

        try {
            Thread.sleep(1000);
            thread.interrupt();
            System.out.println("interrupt thread!");
            Thread.sleep(3000);
            thread.join();
            System.out.println("main stop!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            System.out.println("throw InterruptedException!");
            e.printStackTrace();
        }
        System.out.println("thread stop!");
    }
}

  输出

thread starting...
interrupt thread!
throw InterruptedException!
thread stop!
java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at program.javaTest.threadtest.StopThread.run(StopThread.java:30)
    at java.lang.Thread.run(Thread.java:745)
main stop!

  那么还有个情况,就是调用interrupt()时线程没有处于阻塞,然后线程开始了sleep等三种方法阻塞,这时线程同样会跳入catch (InterruptedException e) {}中,因为中断标志此时为true。

public class StopThread implements Runnable {
    public static void main(String[] args) {
        StopThread stopThread = new StopThread();
        Thread thread = new Thread(stopThread);
        thread.start();
        System.out.println("thread starting...");

        try {
            thread.interrupt();
            System.out.println("isInterrupted : " + thread.isInterrupted());
            Thread.sleep(3000);
            thread.join();
            System.out.println("main stop!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        long l = System.currentTimeMillis();
        while (System.currentTimeMillis() - l < 5000);
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            System.out.println("entry catch block!");
            e.printStackTrace();
        }
        System.out.println("thread stop!");
    }
}

  输出

thread starting...
isInterrupted : true
entry catch block!
java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at program.javaTest.threadtest.StopThread.run(StopThread.java:30) at java.lang.Thread.run(Thread.java:745) thread stop! main stop!

  这个demo中多了一个thread.isInterrupted()方法,它也是用来测试线程中断表示,不同的是,它是实例方法,所以返回的是实例thread的中断标志,这样用来在线程外部管理线程的地方得到线程中断状态;另外isInterrupted()方法不会重置中断标志。用这个方法时有另外一个发现,当线程进入catch后,中断标志重置为false!!!

P.S.interrupt()方法就讲这么多,它和信号变量一起使用可以达到很好的中断线程目的。但是又有了新的问题,现在能够处理sleep等3个阻塞方法,如果线程阻塞在其他方法上,比如IO中的read,该如何处理。这个之后会放在另外一篇博文中详细介绍。

原文地址:https://www.cnblogs.com/wdfwolf3/p/7464260.html