曾经有人说,一个好的技术分享大概就是如下一个流程
是什么
(即该软件是干什么用的)--->干什么
(即该软件的使用场景)-->怎么干
(即具体使用场景的具体使用示例)。 ----鲁迅
反正我是严重不同意这种说法的。因为对于这些小白听众来说,你用来描述是什么
的东西对于他们来说都是 是什么
。下面开始我们今天的主题 【java 的中断
】
中断的原理
让我们从java线程的源码分析开始好了。Thread类中定义了如下几个方法
// 中断的几个方法最终都是通过native方法实现的,关于native方法,我们之后会慢慢研究,这里不做分析
// 我们不要看这个函数里面的代码逻辑,只需要记住interrupt方法是唯一能将中断状态设置为true的方法
public void interrupt() {
if (this != Thread.currentThread())
checkAccess();
synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
interrupt0(); // Just to set the interrupt flag
b.interrupt(this);
return;
}
}
interrupt0();
}
// 这个函数的作用其实是清除中断标志,即将中断标志设置为false。
// 这个函数命名也真是醉了,我怎么感觉使用clearInterrupt更好啊
// 里面的逻辑我们也不用管
//反正我每次都有点搞混,后来就想了个记忆方法,interrupted表示interrupt的过去式,也就是说中断过去了,即中断标志清除了,看来学好英语很重要😂
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
public boolean isInterrupted() {
return isInterrupted(false);
}
中断请求可以来自线程本身也可以来自其它线程,最终只要调用了interrupt() 方法,那么该线程就被"中断"了,这里之所以加了引号,是因为线程并没有被打断,只是中断标志位置为true了,如果线程在该标志位为true时做一些抛出异常的处理,线程就会中断,不处理就跟没事发生一样。线程A只要把线程B的中断标志位设置位true,线程B在合适的时机根据该标志位(调用isInterrupted方法)处理中断就可以了,当然也可以不处理(调用interrupted()进行清除)。
到这里,大家应该也明白了只要线程的interrupt方法被调用了,该线程就会产生中断(
当然前提是你的代码中有对中断作出响应,如果没有,那有中断和没中断没啥区别
)就像你妈喊你回家吃饭,但是回不回是你决定的。
在一些类中中就有些方法就会调用线程的中断方法,比如FutureTask中的cancel方法,如果传入的参数为true,就会调用。
中断的处理
java的中断,说白了就是线程直接的一种协作机制,我告诉你了,你爱听不听,你可以根据自己的实际情况(具体业务场景)选择听还是不听(处理或者不处理)。就像你上学时老师给你讲的大道理,你当时选择一概不听,等多年以后,你忽然理解了,就会选择听了。有点扯远了😄~
我们经常看到某些方法后面抛出InterruptedException,就说明该方法会响应中断,然后该方法的上层调用栈如果检测到中断,清除中断位,然后抛出异常,那么上层方法也成为一个可中断方法
一般的基础类库都不会吞掉该中断
,让上层调用栈去处理
题外话
Thread.stop方法已经停用了,我们就不说了
stop 跟interrupt的一个核心区别就是中断需要程序自己去检测然后做相应的处理,而Thread.stop会直接在代码执行过程中抛出ThreadDeath错误