java线程中断,也是一个比较难懂的点,但是面试会经常问到,其实中断就是有2种情况,一种是可阻塞中断(调用wait、sleep,join 方法),一种是不可阻塞中断(争夺锁sychnrozied)。

对于可中断阻塞而言,我们可以通过线程的

isInterrupted()  interrupt() interrputed()


三个方法来实现: 

  • isInterrupted() 判断线程是否中断
  • interrupt() 中断线程,给线程中断标志设为true 
  • interrputed()  测试当前线程是否已经中断并且线程的“中断状态”由该方法清除。换句话说,如果连续两次调用该方法,则第二次调用将返回 false。这是一个Thread方法,针对的是当前线程,不是调用线程。
/**
     * 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 (unless the current thread were
     * interrupted again, after the first call had cleared its interrupted
     * status and before the second call had examined it).
     *
     * <p>A thread interruption ignored because a thread was not alive
     * at the time of the interrupt will be reflected by this method
     * returning false.
     *
     * @return  <code>true</code> if the current thread has been interrupted;
     *          <code>false</code> otherwise.
     * @see #isInterrupted()
     * @revised 6.0
     */
    public static boolean interrupted() {
        return currentThread().isInterrupted(true);
    }

看看Thread.interrupted方法的具体解释,1 返回的是当前线程的中断标志位状态,2 清除当前线程的中断标志位(如果是true,置为false,是false则不管)。记住是先返回状态,在进行清除,否则就会一直返回false;这样也会有连续调用两次会返回false的情况。

 代码示例

public class MyThread extends Thread {

    @Override
    public void run() {
        super.run();
        System.out.println("线程标志位" + this.isInterrupted());
        System.out.println("执行任务");
        try {
            sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
            System.out.println("异常 线程标志位" + this.isInterrupted());
        }

    }

    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start();
        thread.interrupt();
}

打印结果

执行任务
线程标志位true
异常 线程标志位false
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at com.sjh.interrupt.MyThread.run(MyThread.java:11)

分析:线程启动后,调用线程interrupt 方法,给线程的中断标志位设置为true,但线程sleep时,遇到可中断阻塞后就通过抛出异常来进行中断线程,并且在抛出异常后立即将线程的中断标示位清除,即重新设置为false。同时还要注意interrupt方法只是给线程的标志改变一下,线程是否中断是由线程自己决定的,有可能线程一直都会中断,直到线程执行完,所以说interrupt 中断线程是一种协商机制。

 

不可中断阻塞线程

这种情况,要么线程执行完进行dead状态,也就不必要中断,要么就是那种线程里面是一个死循环,当我们想要中断这种线程,其实就是让他跳出循环,任务执行完就ok 了,

public volatile boolean flag = false;

    public StopThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        super.run();
        while (true){
            if (flag){
                System.out.println("中断");
                break;
            }
            try {
                System.out.println("执行任务");

            }catch (Exception e){
                e.printStackTrace();
                System.out.println("异常");
            }
        }

    }

    public static void main(String[] args) {
        StopThread stopThread = new StopThread("stopThread");
        stopThread.start();

        try {
            Thread.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        stopThread.flag = true;

    }