将run()里面的停顿时间改为是sleep()后,当主线程执行thread.interrupt()的疑问

来源:3-3 Java线程停止广为流传的错误方法---interrupt方法

慕盖茨1011508

2018-08-22 16:57

将run()里面停顿时间改为是sleep()后,当主线程执行thread.interrupt()后,this.isInterrupted()的值为ture,那么while语句应该停止,为什么还会执行Thread.sleep()从而抛出异常?视频8分钟开始那里

写回答 关注

6回答

  • no4990
    2019-07-10 15:22:24

    薇辣酱 说得对, 是概率问题,子线程中while (!this.isInterrupted()) 这句话运行的时间非常短,子线程的绝大部分时间都在Thread.sleep(xxxx);这句话上,所以在主线程中将子线程中断的时候(主线程执行thread.interrupt()的时候),子线程有极大的概率处于sleep中,然后就会报sleep中断错误(sleep interrupted)。


    简单的验证:

    在子线程的sleep语句前后各加一个输出,比如“子线程将睡眠XX秒”和“子线程睡眠结束”,然后你会发现异常都出现在“子线程将睡眠XX秒”这句后面,然后没有出现相匹配的“子线程睡眠结束”,也就是说主线程在将子线程中断的时候,子线程都处于sleep的状态(绝大部分时候)。

    处于非sleep的状态如果真的试出来了,应该是会出现“子线程将睡眠XX秒”和“子线程睡眠结束”,然后子线程退出循环。

  • 薇辣酱
    2019-04-18 05:59:11

    我想明白了,因为thread是从上一次停下来的位置开始运行的,不是从while (!this.isInterrupted())这里开始。而sleep占用了while循环大多数时间,所以上次大概率是在sleep()这里停的。

    所以重新运行的时候,一开始就抛出了InterruptedException异常,同时this.isInterrupted()被置为false。然后while循环就一直运行下去了。

    我将run循环内容做了一些修改,你可以看的更清楚。

    public void run() {

        int i = 0;

        while (!this.isInterrupted()) {

            System.out.println(i);

            try {

                Thread.sleep(4000);

             } catch (InterruptedException e) {

                e.printStackTrace();

                System.out.println(i+1000);

            }

            System.out.println(i);

            i++;

        }

    }

    输出为:

    Starting Thread...

    0

    Interrupting Thread...

    java.lang.InterruptedException: sleep interrupted

    at java.lang.Thread.sleep(Native Method)

    at WrongWayStopThread.run(WrongWayStopThread.java:28)

    1000

    0

    1

    1

    2

    2

    3

    Stopping Application...


  • 薇辣酱
    2019-04-18 04:37:17

    我也没弄明白这个问题,求解答。。。

  • 慕尼黑0535884
    2019-04-08 17:48:16

    this.isInterrupted()是测试线程的状态是否是interrupted的。

    这个状态时由thread.interrupt()方法来置位的,但是thread.interrupt()方法置位为interrupted状态的前提是线程处于非阻塞状态,否则thread.interrupt()只会把interrupted清除并且抛出异常。

    因为这里调用Thread.sleep()使线程处于阻塞状态,所以线程非但没有被置为interrupted,反而抛出了异常。


    while循环的执行大部分时间应该是在Thread.sleep()上的,几乎不可能在Thread.sleep()刚好结束而还没有进行while(true)判断的时候thread.interrupt()置位为interrupted状态

  • 火云邪神的爷爷4298702
    2018-11-13 17:12:03

    thread.interrupt()方法的作用是唤醒阻塞的线程,并抛出异常。当sleep后,线程阻塞,thread.interrupt()方法执行后,线程又被唤醒并抛出异常。因为线程被唤醒,所以this.isInterrupted()的值为false,while语句继续

  • 景阳_洪兵
    2018-08-22 19:27:54

    先抛出的一场,然后重置变量

深入浅出Java多线程

带你一起深入浅出多线程,掌握基础,展望进阶路线

186088 学习 · 464 问题

查看课程

相似问题