关于线程的interrupt与sleep问题

目录

  • 关于线程的interrupt与sleep问题
    • 情况一:自定义线程中写interrupt与sleep
    • 所以以后要用这种方法结束线程,编码时是先写interrupt后写sleep这样才能抛异常。
    • 情况二:主线程中写
    • 所以综上所述,这种方式,还是执行了先interrupt方法后执行了sleep方法才抛出的异常
    • 再换一种情况
    • 但子线程依旧执行了,虽然主线程被打断睡眠抛出了异常还调用了return将主线程结束,线程调度器在主线程结束前执行了子线程。说明线程执行顺序不确定,且在编码中先写interrupt后写sleep才能抛出异常实现想要的结果。

关于这个问题我找到了很多帖子,他们都说:

先sleep,后才能interrupt。 sleep是阻塞,线程会暂时停在这里。interrupt 是打断。只有阻塞的线程被打断了,才会报这个异常。

然后,我作为初学者经过实际的代码测试的时候就很蒙。我们看组代码:

情况一:自定义线程中写interrupt与sleep

public class SubThread4 extends Thread {@Overridepublic void run() {System.out.println("当前线程的名字是:" + Thread.currentThread().getName() + System.currentTimeMillis());System.out.println("线程的id:" + Thread.currentThread().getId());System.out.println("睡眠之后:" + Thread.currentThread().getName() + System.currentTimeMillis());System.out.println("当前状态:" + this.isInterrupted());try {System.out.println(this.isInterrupted());System.out.println("打断后:"+this.isInterrupted());Thread.currentThread().interrupt();sleep(3000);} catch (InterruptedException e) {e.printStackTrace();//打断后你不处理异常,继续执行循环,线程重新继续跑,所以interrupt变成false了//事实证明先打断后sleep才会抛出异常。。。//在子线程的run方法中,如果有异常要处理只能捕获处理,不能抛出处理,因为原run方法不能抛出//            System.out.println("调用过sleep后:"+this.isInterrupted());System.out.println("进入异常");System.out.println(this.isInterrupted());return;}System.out.println("当前状态:" + this.isInterrupted());System.out.println("这个线程执行完了!");}}

public class SubThread4 extends Thread {@Overridepublic void run() {System.out.println("当前线程的名字是:" + Thread.currentThread().getName() + System.currentTimeMillis());System.out.println("线程的id:" + Thread.currentThread().getId());System.out.println("睡眠之后:" + Thread.currentThread().getName() + System.currentTimeMillis());System.out.println("当前状态:" + this.isInterrupted());try {System.out.println(this.isInterrupted());System.out.println("打断后:"+this.isInterrupted());sleep(3000);Thread.currentThread().interrupt();} catch (InterruptedException e) {e.printStackTrace();//打断后你不处理异常,继续执行循环,线程重新继续跑,所以interrupt变成false了//事实证明先打断后sleep才会抛出异常。。。//在子线程的run方法中,如果有异常要处理只能捕获处理,不能抛出处理,因为原run方法不能抛出//            System.out.println("调用过sleep后:"+this.isInterrupted());System.out.println("进入异常");System.out.println(this.isInterrupted());return;}System.out.println("当前状态:" + this.isInterrupted());System.out.println("这个线程执行完了!");}}


      这两组代码只有sleep(3000);和Thread.currentThread().interrupt();这两行代码调换位置,这一点不同,其余部分完全一样。
      但结果好像和网上说的“先sleep,后才能interrupt,抛异常”顺序不一样啊!实际上它们是一样的,网上的分析都光分析了内部原理内部原理确实是先sleep后interrupt就会抛出异常,但他们都没说实际编码是个啥样,我也是想了半天才晕过来,在实际编程中我们的sleep调用的是Thread为我们封装好的sleep方法,也就是说sleep已经封装好了,你不可能在sleep的每一毫秒过程中都去检测或者调用interrupt方法。编码中的sleep是一个整体,它需要完全睡完,之后才能执行第二行的Thread.currentThread().interrupt();,而这个时候它都已经睡完了当然不会发生sleep中打断的情况,所以编码的这个时候 先sleep(3000);后Thread.currentThread().interrupt();是没有任何异常的。
      相反的,先使用Thread.currentThread().interrupt();将线程的中断标志调为true,这个时候我们再来写sleep(3000);它会发现中断标记已经为true了,它没法再阻塞这个线程了,就会出现异常并捕获异常。注意:这个时候它会捕获异常是不假,但它并不会返回,我们需要手动在catch中加一个return;返回并结束线程,这个也是线程的特性,它只会捕获但并不能将异常抛出后结束线程。

所以以后要用这种方法结束线程,编码时是先写interrupt后写sleep这样才能抛异常。

情况二:主线程中写

这种就是大概这样你写好了自定义线程代码(就把Thread.currentThread().interrupt();删掉了interrupt();放在主线程里面):

public class SubThread4 extends Thread {@Overridepublic void run() {System.out.println("当前线程的名字是:" + Thread.currentThread().getName() + System.currentTimeMillis());System.out.println("线程的id:" + Thread.currentThread().getId());System.out.println("睡眠之后:" + Thread.currentThread().getName() + System.currentTimeMillis());System.out.println("当前状态:" + this.isInterrupted());try {System.out.println(this.isInterrupted());System.out.println("打断后:"+this.isInterrupted());
//            Thread.currentThread().interrupt();sleep(3000);} catch (InterruptedException e) {e.printStackTrace();//打断后你不处理异常,继续执行循环,线程重新继续跑,所以interrupt变成false了//事实证明先打断后sleep才会抛出异常。。。//在子线程的run方法中,如果有异常要处理只能捕获处理,不能抛出处理,因为原run方法不能抛出//            System.out.println("调用过sleep后:"+this.isInterrupted());System.out.println("进入异常");System.out.println(this.isInterrupted());return;}System.out.println("当前状态:" + this.isInterrupted());System.out.println("这个线程执行完了!");}}

主方法:

public class Test {public static void main(String[] args) {System.out.println(Thread.currentThread().getName()+" , id = "+Thread.currentThread().getId());SubThread4 t4 = new SubThread4();System.out.println("当前时间:"+System.currentTimeMillis());t4.start();t4.interrupt();System.out.println("睡眠之后的时间:"+System.currentTimeMillis());}
}

结果:

      你可能觉得interrupt在线程start之后但还是抛出异常信息了,是不是编码按照先sleep后interrupt的顺序执行了呢? 错! 代码执行顺序依旧是先interrupt后sleep所以才抛得异常信息。 因为主线程里面开别的线程的方式虽然是直接调用start方法,但start方法调用后线程并没有直接执行,而是将该线程交给了线程调度器(schedule) 线程真正什么时候运行是不确定的。(但是一般都是main线程执行完才开始执行别的线程的 ,这里的一般是指JDK1.8在IDEA2018上的执行顺序,没错这就是我电脑的环境。。。XD)

所以综上所述,这种方式,还是执行了先interrupt方法后执行了sleep方法才抛出的异常

再换一种情况

代码:

public class SubThread4 extends Thread {@Overridepublic void run() {System.out.println("当前线程的名字是:" + Thread.currentThread().getName() + System.currentTimeMillis());System.out.println("线程的id:" + Thread.currentThread().getId());System.out.println("睡眠之后:" + Thread.currentThread().getName() + System.currentTimeMillis());System.out.println("当前状态:" + this.isInterrupted());
//        try {//            System.out.println(this.isInterrupted());
//            System.out.println("打断后:"+this.isInterrupted());
            Thread.currentThread().interrupt();
//            sleep(3000);
//        } catch (InterruptedException e) {//            e.printStackTrace();
//            //打断后你不处理异常,继续执行循环,线程重新继续跑,所以interrupt变成false了
//            //事实证明先打断后sleep才会抛出异常。。。
//            //在子线程的run方法中,如果有异常要处理只能捕获处理,不能抛出处理,因为原run方法不能抛出
//            //            System.out.println("调用过sleep后:"+this.isInterrupted());
            System.out.println("进入异常");
            System.out.println(this.isInterrupted());
            return;
//        }System.out.println("当前状态:" + this.isInterrupted());System.out.println("这个线程执行完了!");}}

主线程:

public class Test {public static void main(String[] args) {System.out.println(Thread.currentThread().getName()+" , id = "+Thread.currentThread().getId());SubThread4 t4 = new SubThread4();System.out.println("当前时间:"+System.currentTimeMillis());t4.start();
//        try {//            sleep(4000);
//        } catch (InterruptedException e) {//            e.printStackTrace();
//        }Thread.currentThread().interrupt();try {sleep(4000);} catch (InterruptedException e) {e.printStackTrace();return;}//        t4.interrupt();System.out.println("睡眠之后的时间:"+System.currentTimeMillis());}
}

结果:

我们可以很明显的看到主线程被打断了

主线程中这一句代码没有执行。
      但子线程执行了,你可能会在一开始觉得子线程永远在主线程运行完才执行,主线程要停了子线程就不执行了。

但子线程依旧执行了,虽然主线程被打断睡眠抛出了异常还调用了return将主线程结束,线程调度器在主线程结束前执行了子线程。说明线程执行顺序不确定,且在编码中先写interrupt后写sleep才能抛出异常实现想要的结果。

关于线程的interrupt与sleep问题相关推荐

  1. JAVA线程的interrupt

    interrupt()只是改变中断状态而已. interrupt()不会中断一个正在运行的线程.这一方法实际上完成的是,给受阻塞的线程抛出一个中断信号,     这样受阻线程就得以退出阻塞的状态.更确 ...

  2. 调用方法try起来的好处_Java:一个重要的停止线程方法——interrupt

    一.前言 之前本人写了一篇防止Controller中的线程被重复调用的文章,大概代码如下: //sonarqube检查要求static变量必须是final,为避开检查,使用final HashMapp ...

  3. 线程中断interrupt

    线程中的中断标志位 一. 与线程中断有关的3个方法: interrupt():中断线程,改变其线程的中断标志位(仅仅只有一个通知的作用),但是否中断由自己线程判断决定.false-->true ...

  4. 怎么查看线程的状态及interrupt优雅的关闭线程和interrupt()、interrupted()、isInterrupted()的作用以及区别在哪?

    怎么查看线程状态 jps指令查看我当前的进程ID jstack 线程ID 示例: public class StatusDemo {public static void main(String[] a ...

  5. 线程中断机制 interrupt、isInterrupted、interrupted方法

    ①. 什么是中断 ①. 一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止,所以,Thread.stop.Thread.suspend.Thread. resume都已经被废弃了 ② ...

  6. 线程中断 interrupt

    Java的中断是一种协作机制.也就是说调用线程对象的interrupt方法并不一定就中断了正在运行的线程,它只是要求线程自己在合适的时机中断自己.每个线程都有一个boolean的中断状态(这个状态不在 ...

  7. 线程的interrupt

    中断在java中主要有3个方法,interrupt(),isInterrupted()和interrupted() public void interrupt() {if (this != Threa ...

  8. java 中断线程 wait_Java 线程中断(interrupt)与阻塞 (park)的区别

    很多Java开发人员(包括我),尤其是刚进入软件行业的新手,认为Java设置线程中断就是表示线程停止了,不往前执行了, Thread.currentThread().interrupt() 其实不是这 ...

  9. java线程interrupt用法_Java线程中interrupt那点事 | 学步园

    1.先看一下例子程序: import java.io.IOException; import java.net.ServerSocket; import javax.rmi.CORBA.Tie; /* ...

最新文章

  1. GNU make 和 makefile
  2. windows下载anaconda3速度太慢怎么办
  3. c语言变量及输入输出
  4. 从实例学习多态(Polymorphism [pɔli'mɔ:fizm])
  5. echarts 折线图 多条折线数据相同时展示的图形并没有重合
  6. python3.5安装scrapy_在Python3.5下安装和测试Scrapy爬网站
  7. 计算机维修实训报告模板,[计算机维修实验报告模板.doc
  8. 深入Atlas系列:Web Sevices Access in Atlas示例(3) - 在Web Services方法中使用多态
  9. 简单快捷的Amaze UI框架搭建
  10. Java传输文件使用Base64优化传输速率。
  11. oracle dbms_utility,dbms_utility的两个有用方法
  12. mvp的全称_王者荣耀里面每把有mvp但是mvp是什么意思呢
  13. 文章推荐列表(个人收藏)
  14. 智慧家安监控系统——用Java + html、css、js实现
  15. window系统下安装VS(Microsoft Visual Studio),及Visual Studio使用教程
  16. gets 、getchar 、fgets 、scanf的用法
  17. 单片机中的浮点数转换成串口可打印格式
  18. CSS-Sprite(雪碧图)
  19. librosa.load报错。audioread.NoBackendError
  20. 线性代数(十一) : 列空间与零空间的进一步介绍

热门文章

  1. Android9.0 完全隐藏导航栏、状态栏
  2. Unity3D 网页插件Embedded Browser(ZFBrowser)PC端打包文件无法加载网页解决方法
  3. 华为与复旦大学合作开发全国首个医学人工智能课程
  4. VVC帧间预测(十)帧间帧内联合预测CIIP
  5. 简单概述PCIe总线协议
  6. 安装pycrypto
  7. 有趣的“灵魂”库集合
  8. 数据库的备份和恢复(笔记)
  9. JavaScript中 FormData 对象详解
  10. ffmpeg去除水印