调用interrupt方法后,可以中断掉线程。这里所说中断掉线程,是指下面其中一种结果。
(1)线程变成“中断状态”对“状态”的反应;
(2)抛出“异常InterruptedException”对“控制”的反应。
通常会使(1)。只有在线程是sleep、wait、join时会是(2)(这个时候不会变成中断状态)。
然而,状态(1)、(2)是可以相互转换的。也就是说,可以把(1)变为(2),也可以把(2)变为(1)。配合程序的需要——大致上就是为了让程序不至于忘记被中断的事实——而加以变化。
下面是具体的说明:
中断状态 -> InterruptedException异常的转换
“若线程是中断状态,就抛出InterruptedException异常”,可以像下面这样写。其中interrupted方法,是java.lang.Thread类的类方法。
if(Thread.interrupted()){ throw new InterruptedException(); }
在花时间的处理前,先加上这个if语句,可提高程序对中断的响应性。可以避免不知道自己已经被中断,还开始进行花时间的处理。
反倒是,这个if语句乍看之下很简单,要完全了解倒比想象中复杂许多。
哪个线程来检查interrupted方法
Thread.interrupted方法,会检查Thread.currentThread()的中断状态。也就是说,上面的if语句无论卸载哪个类的哪个方法,都是检查执行if语句的线程的中断状态。
不想清除中断状态的时候
调用Thread.interrupted方法后,线程就不是中断状态了。也就是说,只要调用一次Thread.interrupted方法后,中断状态就会被清除。
如果不想清除中断状态,而要检查现在线程是否被中断,要使用isInterrupted实例方法。调用方式如下:
if(Thread.currentThread.isInterrupted()){ //若为中断中断时需要进行的处理(中断状态不会清除) }
InterruptedException异常 -> 转换为中断状态
想要让线程只有在指定的时间才停止时,可以使用Thread.sleep方法。因为Thread.sleep会抛出InterruptedException异常,所以可能我们需要经常会这样写:
try { Thread.sleep(1000); } catch (InterruptedException e){ }
不过,这样写的话,抛出的InterruptedException异常会被忽略。当sleep被其他线程interrupt时,“被中断”这个事实会消失。
若当我们不希望被中断这个事实消失时,就像下面这样,自己再重新中断自己一次。
try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread.interrupt(); }
这样可以将收到的InterruptedException异常转换为中断状态的形式。
InterruptedException异常 -> 转换为InterruptedException异常
收到的InterruptedException异常,也可以不马上抛出来,而留下来晚点再抛。如下:
InterruptedException savedException = null; ... try { Thread.sleep(1000); } catch (InterruptedException e) { savedException = e; } ... if (savedException != null){ throw savedException; }
在这里,先将收到的InterruptedException存在变量savedException里,留到后面才throw出去。
内容来源于《Java多线程设计模式》一书,方便以后查看。