• 【Java多线程】Thread类中interrupt()、interrupted() 和isInterrupted() 方法详解(九)


    方法官方说明

    interrupt()方法

      

      其作用是中断此线程(此线程不一定是当前线程,而是指调用该方法的Thread实例所代表的线程),但实际上只是给线程设置一个中断标志,线程仍会继续运行。

    interrupted()方法

      

      作用是测试当前线程是否被中断(检查中断标志),返回一个boolean并清除中断状态,第二次再调用时中断状态已经被清除,将返回一个false。

    isInterrupted()方法

      

      作用是只测试此线程是否被中断 ,不清除中断状态。

    示例说明

    验证interrupt()方法

      定义一个MyThread类,继承Thread,如下:

     1 class MyThread extends Thread {
     2     @Override
     3     public  void run() {
     4         long num = 1;
     5         for (int i = 1; i < 1000000000; i++) {
     6             num = num * (num + i) % 1000000000;
     7         }
     8         System.out.println("结果是" + num);
     9         System.out.println("退出线程" + Thread.currentThread().getName());
    10     }
    11 }

      在main方法中测试

     1 public class TestInterrupt {
     2 
     3     public static void main(String[] args ) {
     4         MyThread thread=new MyThread();
     5         thread.start();
     6         thread.interrupt();
     7         // 测试 isInterrupted()函数
     8         System.out.println("第一次调用thread.isInterrupted():"+thread.isInterrupted());
     9         System.out.println("第二次调用thread.isInterrupted():"+thread.isInterrupted());
    10         System.out.println("thread是否存活:"+thread.isAlive());
    11     }
    12 
    13 }

      输出如下:

      

      分析:

    1. 调用interrupt()方法后,线程设置一个中断标志
    2. 结果看出调用interrupt()方法后,线程仍在继续运行,并未停止,两个isInterrupted()方法都会输出true,也说明isInterrupted()方法并不会清除中断状态。

    验证interrupt()方法

    • 代码一

      下面我们把代码修改一下,多加两行调用interrupted()方法:

     1 public class TestInterrupt {
     2 
     3     public static void main(String[] args ) {
     4         MyThread thread=new MyThread();
     5         thread.start();
     6         thread.interrupt();
     7         // 测试 isInterrupted()函数
     8         System.out.println("第一次调用thread.isInterrupted():"+thread.isInterrupted());
     9         System.out.println("第二次调用thread.isInterrupted():"+thread.isInterrupted());
    10         // 测试 interrupted()函数
    11         System.out.println("第一次调用thread.interrupted():"+thread.interrupted());
    12         System.out.println("第二次调用thread.interrupted():"+thread.interrupted());
    13         System.out.println("thread是否存活:"+thread.isAlive());
    14     }
    15 }

      输出如下:

      

      从输出结果看,可能会有疑惑,为什么后面两个interrupted方法输出的都是false,而不是预料中的一个true一个false?注意!!!这是一个坑!!!上面说到,interrupted()方法测试的是当前线程是否被中断,当前线程!!!当前线程!!!这里当前线程是main线程,而thread.interrupt()中断的是thread线程,这里的此线程就是thread线程。所以当前线程main从未被中断过,尽管interrupted()方法是以thread.interrupted()的形式被调用,但它检测的仍然是main线程而不是检测thread线程,所以thread.interrupted()在这里相当于main.interrupted()

      查看interrupted()源码

    1 public class Thread implements Runnable {
    2     .....
    3 
    4     public static boolean interrupted() {
    5         return currentThread().isInterrupted(true);
    6     }
    7 
    8     .....
    9 }  

      interrupted()是一个静态方法,调用的currentThread()方法来获取当前线程(在代码中当前线程即主线程main) 

      对于这点,下面我们再修改进行测试。

     1 public class TestInterrupt {
     2 
     3     public static void main(String[] args ) {
     4         MyThread thread=new MyThread();
     5         thread.start();
     6         thread.interrupt();
     7         // 测试 isInterrupted()函数
     8         System.out.println("第一次调用thread.isInterrupted():"+thread.isInterrupted());
     9         System.out.println("第二次调用thread.isInterrupted():"+thread.isInterrupted());
    10         // 测试 interrupted()函数
    11         System.out.println("第一次调用thread.interrupted():"+Thread.currentThread().interrupted());
    12         System.out.println("第二次调用thread.interrupted():"+Thread.currentThread().interrupted());
    13         System.out.println("thread是否存活:"+thread.isAlive());
    14     }
    15 }

      运行结果前面相同

      

    • 代码二
     1 public class TestInterrupt2 {
     2 
     3     public static void main(String[] args ) {
     4         Thread.currentThread().interrupt();
     5         // 测试 isInterrupted()函数
     6         System.out.println("第一次调用Thread.currentThread().isInterrupted():"+Thread.currentThread().isInterrupted());
     7         System.out.println("第二次调用Thread.currentThread()v.isInterrupted():"+Thread.currentThread().isInterrupted());
     8         // 测试 interrupted()函数
     9         System.out.println("第一次调用Thread().interrupted():"+Thread.currentThread().interrupted());
    10         System.out.println("第二次调用Thread().interrupted():"+Thread.currentThread().interrupted());
    11         System.out.println("Thread.currentThread()是否存活:"+Thread.currentThread().isAlive());
    12     }
    13 
    14 }

      运行结果:

      

      这里都是针对当前线程在操作,如果interrupted()方法有检测中断并清除中断状态的作用

    • 代码三

      若果想要是实现调用interrupt()方法真正的终止线程,则可以在线程的run方法中做处理即可,比如直接跳出run()方法使线程结束,视具体情况而定,下面是一个例子。

     1 public class TestInterrupt3 {
     2 
     3     public static void main(String[] args) {
     4         MyThread3 thread=new MyThread3();
     5         thread.start();
     6         thread.interrupt();
     7         //sleep等待10秒,等myThread运行完
     8         try {
     9             Thread.currentThread().sleep(10000);
    10         } catch (InterruptedException e) {
    11             e.printStackTrace();
    12         }
    13         System.out.println("myThread线程是否存活:"+thread.isAlive());
    14     }
    15 
    16 }
    17 
    18 class MyThread3 extends Thread {
    19 
    20     @Override
    21     public void run() {
    22         long num = 1;
    23         for (int i = 1; i < 1000000000; i++) {
    24             num = num * (num + i) % 1000000000;
    25             if (this.isInterrupted()) {
    26                 System.out.println("通过this.isInterrupted()检测到中断");
    27                 System.out.println("第一个interrupted()" + Thread.interrupted());
    28                 System.out.println("第二个interrupted()" + Thread.interrupted());
    29                 System.out.println("因为检测到中断,所以跳出循环,线程到这里结束,因为后面没有内容了");
    30                 return;
    31             }
    32         }
    33         System.out.println("结果是" + num);
    34         System.out.println("退出线程" + Thread.currentThread().getName());
    35     }
    36 }

      运行结果:

      

    • 代码四

      interrupt() 除了给线程设置中断标志,还能将处于中断状态的线程唤醒,代码如下

     1 public class TestInterrupt4 {
     2 
     3     public static void main(String[] args) {
     4         MyThread4 thread=new MyThread4();
     5         thread.start();
     6         try {
     7             Thread.sleep(1000);
     8         } catch (InterruptedException e) {
     9             e.printStackTrace();
    10         }
    11         //  除了给线程设置中断标志,还能将处于中断状态的线程唤醒
    12         thread.interrupt();
    13     }
    14 
    15 }
    16 
    17 class MyThread4 extends Thread {
    18     @Override
    19     public  void run() {
    20         long start = System.currentTimeMillis();
    21         try {
    22             Thread.sleep(100000000);
    23         } catch (InterruptedException e) {
    24             e.printStackTrace();
    25         }
    26         long end = System.currentTimeMillis();
    27         System.out.println("线程休眠时间为" + (end - start) + "毫秒");
    28     }
    29 }

      运行结果:

      

    最后总结

      关于这三个方法,interrupt() 是给线程设置中断标志;interrupted() 是检测中断并清除中断状态;isInterrupted() 只检测中断。还有重要的一点就是interrupted() 作用于当前线程,是静态方法,interrupt() 和isInterrupted() 作用于此线程,即代码中调用此方法的实例所代表的线程。

    原文链接:https://blog.csdn.net/qq_39682377/article/details/81449451

  • 相关阅读:
    AcWing242一个简单的整数问题1(差分+树状数组)
    AcWing241楼兰图腾(树状数组)
    AcWing802区间和
    离散化
    AcWing1250格子游戏(并查集)
    vijos难解的问题(LIS最长上升子序列)
    动态规划dp——LIS(最长上升子序列)、LCS(最长公共子序列)
    约数、素数、gcd(最大公约数)、lcm(最小公倍数)
    vijos拓扑编号(逆向拓扑排序+优先队列)
    洛谷P1137旅行计划(拓扑排序+简单dp)
  • 原文地址:https://www.cnblogs.com/h--d/p/14557647.html
Copyright © 2020-2023  润新知