将run()里面的停顿时间改为是sleep()后,当主线程执行thread.interrupt()的疑问
将run()里面停顿时间改为是sleep()后,当主线程执行thread.interrupt()后,this.isInterrupted()的值为ture,那么while语句应该停止,为什么还会执行Thread.sleep()从而抛出异常?视频8分钟开始那里
将run()里面停顿时间改为是sleep()后,当主线程执行thread.interrupt()后,this.isInterrupted()的值为ture,那么while语句应该停止,为什么还会执行Thread.sleep()从而抛出异常?视频8分钟开始那里
2018-08-22
薇辣酱 说得对, 是概率问题,子线程中while (!this.isInterrupted()) 这句话运行的时间非常短,子线程的绝大部分时间都在Thread.sleep(xxxx);这句话上,所以在主线程中将子线程中断的时候(主线程执行thread.interrupt()的时候),子线程有极大的概率处于sleep中,然后就会报sleep中断错误(sleep interrupted)。
简单的验证:
在子线程的sleep语句前后各加一个输出,比如“子线程将睡眠XX秒”和“子线程睡眠结束”,然后你会发现异常都出现在“子线程将睡眠XX秒”这句后面,然后没有出现相匹配的“子线程睡眠结束”,也就是说主线程在将子线程中断的时候,子线程都处于sleep的状态(绝大部分时候)。
处于非sleep的状态如果真的试出来了,应该是会出现“子线程将睡眠XX秒”和“子线程睡眠结束”,然后子线程退出循环。
我想明白了,因为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...
this.isInterrupted()是测试线程的状态是否是interrupted的。
这个状态时由thread.interrupt()方法来置位的,但是thread.interrupt()方法置位为interrupted状态的前提是线程处于非阻塞状态,否则thread.interrupt()只会把interrupted清除并且抛出异常。
因为这里调用Thread.sleep()使线程处于阻塞状态,所以线程非但没有被置为interrupted,反而抛出了异常。
while循环的执行大部分时间应该是在Thread.sleep()上的,几乎不可能在Thread.sleep()刚好结束而还没有进行while(true)判断的时候thread.interrupt()置位为interrupted状态
举报