线程的interrupt方法只是请求终止这个线程,而不是强制终止这个线程(总感觉这个方法名带有欺骗性,明明是中断的意思,却不中断线程,改成notifyInterrupt感觉更贴切些)。

    1. public static void main(String[] args) throws InterruptedException {
    2. Runnable r = () -> {
    3. for (int i = 0; i < 2000; i++) {
    4. System.out.println(i);
    5. }
    6. };
    7. Thread t = new Thread(r);
    8. t.start();
    9. t.interrupt();
    10. System.out.println("请求终止t线程");
    11. }

    image.png
    image.png
    我们看到尽管在程序一开始就向线程t发出了终止请求,但是线程t却依旧跑完了任务,并没有因为被调用interrupt而终止。

    这时候你可能会有个疑问:既然interrupt方法并不会中断线程,那这个方法有什么用呢?interrupt方法会给线程设置上一个中断的标记,我们可以通过isInterrupted方法来判断这个线程是否被请求中断,从而在任务中选择如何处理中断。

    1. public static void main(String[] args) throws InterruptedException {
    2. Runnable r = () -> {
    3. for (int i = 0; i < 2000; i++) {
    4. System.out.println(i);
    5. boolean interrupted = Thread.currentThread().isInterrupted(); //默认情况下返回的是false,当线程被调用了interrupt方法后,会返回true
    6. if (interrupted) {
    7. System.out.println("收到线程终止请求,任务结束");
    8. break;
    9. }
    10. }
    11. };
    12. Thread t = new Thread(r);
    13. t.start();
    14. t.interrupt();
    15. System.out.println("请求终止t线程");
    16. }

    在上面代码中,我们通过Thread.currentThread方法获取到线程,然后调用线程实例的isInterruptd方法得到线程是否被请求终止。如果被请求终止,就结束这个for循环。
    image.png

    当一个线程是中断状态的时候,如果调用sleep或者wait,线程非但不会进入阻塞,而且还会抛出InterruptException

    1. public static void main(String[] args) {
    2. Runnable r = () -> {
    3. Thread currentThread = Thread.currentThread();
    4. System.out.println("中断状态" + currentThread.isInterrupted());
    5. try {
    6. Thread.sleep(10000);
    7. } catch (InterruptedException e) {
    8. e.printStackTrace();
    9. }
    10. System.out.println("线程苏醒了");
    11. System.out.println("中断状态" + currentThread.isInterrupted());
    12. };
    13. Thread t = new Thread(r);
    14. t.start();
    15. t.interrupt();
    16. }

    image.png
    我们可以看到,当我们对t线程调用了interrupt之后,t线程的中断状态变成了true,接着让t线程sleep,线程不但没有休眠,而且直接就抛出异常了。同时我们还可以发现,在线程调用sleep之后,中断状态就被清除了

    以上代码我们证明了线程先进入中断状态,再被阻塞的时候,会抛出InterruptException。那么当线程先进入阻塞(sleep或wait)的时候,再被调用interrupt,又会如何呢?
    下面我们用代码求证一下

    1. public static void main(String[] args) throws InterruptedException {
    2. Runnable r = () -> {
    3. Thread currentThread = Thread.currentThread();
    4. System.out.println("中断状态" + currentThread.isInterrupted());
    5. try {
    6. Thread.sleep(10000);
    7. } catch (InterruptedException e) {
    8. e.printStackTrace();
    9. }
    10. System.out.println("线程苏醒了");
    11. System.out.println("中断状态" + currentThread.isInterrupted());
    12. };
    13. Thread t = new Thread(r);
    14. t.start();
    15. Thread.sleep(1000); //这里我们让main线程等待1秒再去执行t线程的interrupt。以确保t线程能够进入休眠
    16. t.interrupt();
    17. }

    image.png
    我们发现,对一个阻塞的线程调用interrupt方法,线程也会抛出InterruptException异常。

    线程还有一个静态方法interrupted,它和isInterrupted一样都会检查当前线程是否被中断。但是不同之处在于interrupted会清除当前线程的中断状态,而isInterrupted不会。