为什么使用interrupt()中断而放弃了stop()方法终止线程;
interrupt方法是一个让我们程序员优雅的中断线程的方法,
因为JVM不推荐直接停止一个线程,直接停止线程可能导致资源没有及时释放,会产生不安全的问题—jvm一定要让一个线程执行完成!
jvm一定要让一个线程执行完成 —假设现在线程在阻塞–interrupt可以解阻塞—继续往下执行
jvm一定要让一个线程执行完成 —假设线程是while (!flag)–flag=th.isInterrupted() --false

案例:

/**
 * 这里需要注意一下,try catch到InterruptedException e异常时,中断信号会被抹除,
 * 所以th.isInterrupted()如果执行在catch异常前,则isInterrupted为true,可以正常退出,否则中断信号抹除后,
 * isInterrupted得到的值为false,故还是死循环
 */
public class ThreadInterruptLuban {
    static Thread th=new Thread();
    public static boolean flag=false;
    public static void main(String[] args) {
        th = new Thread(() -> {
            while (!flag) {
                try {
                    System.out.println("im in while true");
                    TimeUnit.SECONDS.sleep(4);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    System.out.println("-------"+th.isInterrupted());
                }
                System.out.println("-----next");



                System.out.println(th.isInterrupted());
            }
        });
        th.start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        th.interrupt();
        flag=th.isInterrupted();
        System.out.println("flag : "+flag);
    }

}

一、interrupt

当当前线程被进入阻塞状态,若另外的一个线程调用被阻塞的interrupt方法,则会打断这种阻塞,因此这种方法有时会被称为可中断方法,记住,打断一个线程并不等于该线程的生命周期结束,仅仅是打断了当前线程的阻塞状态。
一但线程在阻塞的情况下被打断,都会抛出InterruptedException的异常,这个异常就像一个signal(信号)一样通知当前线程被打断了。
实例:

/**
 * Created by yd on 2019/5/30.
 */
public class ThreadInterrupt {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread() {
            @Override
            public void run() {
                try {
                    TimeUnit.MINUTES.sleep(1);
                } catch (InterruptedException e) {
                    System.out.println("Oh, I am be interrupted");
                }
            }
        };
        thread.start();
        TimeUnit.MILLISECONDS.sleep(2);
        thread.interrupt();
    }
}

运行结果:

Oh, I am be interrupted

二、isInterrupted()

isInterrupted主要判断当前线程是否被中断,该方法仅是对interrupt标识的一个判断,并不会影响标识发生任何改变!
案例:

public class ThreadidInterrupted {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread() {
            @Override
            public void run() {
                while (true) {
                    //do nothing,just empty loop
                }
            }
        };
        thread.start();
        TimeUnit.MILLISECONDS.sleep(2);
        System.out.printf("Thread is interrupted ? %s\n", thread.isInterrupted());
        thread.interrupt();
        System.out.printf("Thread is interrupted ? %s\n", thread.isInterrupted());
    }
}

运行结果:

Thread is interrupted ? false
Thread is interrupted ? true

请注意:

可中断方法捕获到了中断信号(signal)之后,也就是捕获了InterruptedException异常后会擦除掉interrupt标识。

由于在run方法中使用了sleep这个可中断方法,它会捕获到中断信号,并且会擦除interrupt标识,因此程序的执行结果都会是false;

案例2:

public class ThreadidInterrupted2 {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread() {
            @Override
            public void run() {
                while (true) {
                    try {
                        TimeUnit.MINUTES.sleep(1);
                    } catch (InterruptedException e) {
                        System.out.printf("I am be interrupted ? %s\n", isInterrupted());
                    }
                }
            }
        };
        thread.setDaemon(true);
        thread.start();
        TimeUnit.MILLISECONDS.sleep(2);
        System.out.printf("Thread is interrupted ? %s\n", thread.isInterrupted());
        thread.interrupt();
        TimeUnit.MILLISECONDS.sleep(2);
        System.out.printf("Thread is interrupted ? %s\n", thread.isInterrupted());
    }
}

运行结果:

Thread is interrupted ? false
I am be interrupted ? false
Thread is interrupted ? false

其实这也不难理解,可中断方法捕获到了中断信号之后,为了不影响线程中其他方法的执行,将线程的interrupt标识复位是一种合理的设计。

三、interrupted()方法

interrupted是一个静态方法,虽然其也用于判断当前线程是否被中断,但是它和成员方法isInterrupted有很大区别,调用该方法会直接擦除掉线程的interrupt标识,需要注意的是,如果当前线程被打断了,那么第一次调用interrupted方法会返回true,并且立即擦除了interrupt标识;第二次包括以后的调用永远都会返回false,除非在此期间线程又一次被打断。
案例:

public class ThreadidInterrupted3 {
    public static void main(String[] args) throws InterruptedException {
        //1、判断当前线程是否被中断
        System.out.println("main is interrupted ? " + Thread.interrupted());
        //2、中断当前线程
        Thread.currentThread().interrupt();
        //3、判断当前线程是否被已经中断
        System.out.println("main is isInterrupted ? " + Thread.currentThread().isInterrupted());

        //线程发生中断,第一次调用,返回true,并擦除标识
        System.out.println("main is interrupted ? " + Thread.interrupted());
        //第二次false
        System.out.println("main is interrupted ? " + Thread.interrupted());
        try {
            //4、当前线程 执行可中断
            TimeUnit.MINUTES.sleep(1);
        } catch (InterruptedException e) {
            //因为interrupted()擦除了中断标识,所以无法进入捕获异常处理
            //5、捕获中断信号
            System.out.printf("I will be interrupted still.");
        }
    }
}

运行结果:

main is interrupted ? false
main is isInterrupted ? true
main is interrupted ? true
main is interrupted ? false

线程中断时,调用interrupted会立即擦除了interrupt标识,所以无法进入捕获InterruptedException异常的处理逻辑中!