在以前可以通过thread.stop()可以让一个线程去停止另一个线程,但这种方法太暴力,突然间停止其他线程会导致被停止的线程无法完成一些清理工作,所以stop()已经被抛弃了。而Thread.interrupt的作用其实不是中断线程,而是通知线程应该中断了,给这个线程发一个信号,告诉它,它应该结束了,设置一个停止标志, 具体到底中断还是运行,应该由被通知的线程自己处理。具体来说,对一个线程,调用interrupt()时:
- 如果一个线程处于了阻塞状态(如线程调用了thread.sleep、thread.join、thread.wait、1.5中的condition.await、以及可中断的通道上的 I/O 操作方法后可进入阻塞状态),则在线程在检查中断标示时如果发现中断标示为true,则会在这些阻塞方法(sleep、join、wait、1.5中的condition.await及可中断的通道上的 I/O 操作方法)调用处抛出InterruptedException异常,
- 如果线程处于正常活动状态,那么会将该线程中的中断标志设置为true,仅此而已, 被设置中断标志的线程将继续正常执行,不受影响。
interrupt()并不能真正中断线程,需要被调用的线程自己进行配合才行。一个线程如果有被中断的需求,那么就可以这样做: - 在正常运行任务时,经常检查本线程的中断标志位,如果被设置了中断标志,就自行停止线程
- 在调用阻塞方法时正常处理InterruptException异常,
hread thread = new Thread(() -> {
while (!Thread.interrupted()) {
// do more work.
}
});
thread.start();
// 一段时间以后
thread.interrupt();
上面代码中thread.interrupted()清除标志位是为了下次继续监测标志位,不然会对被中断线程的下次运行有影响。通过interrupt()和.interrupted()方法两者的配合可以实现正常去停止一个线程,线程A通过调用线程B的interrupt方法通知线程B让它结束线程,在线程B的run方法内部,通过循环检查.interrupted()方法是否为真来接收线程A的信号,如果为真就可以抛出一个异常,在catch中完成一些清理工作,然后结束线程。Thread.interrupted()会清除标志位,并不是代表线程又恢复了,可以理解为仅仅是代表它已经响应完了这个中断信号然后又重新置为可以再次接收信号的状态。从始至终,理解一个关键点,interrupt()方法仅仅是改变一个标志位的值而已,和线程的状态并没有必然的联系。
网友评论