关于线程中断的理解
什么是中断?中断可以理解为线程的一个标识位属性,代表一个运行中的线程是否被其他线程进行了中断操作。它是一种协作机制,线程可以通过这种机制来通知另一个线程,告诉它在合适的或者可能的情况下停止当前工作,并转而执行其他的工作。
interrupt()方法
我们知道,要想中断一个线程,那么就调用该线程的interrupt()方法,然后该线程就被中断了。然后呢?线程就停止运行了吗?当然不是,这取决于线程执行的方法是否是响应中断的。什么叫响应中断?就是在run方法中,会在运行时不断的检查中断标志,如果中断标志为true,表明线程被中断了,那么接下来线程是继续运行还是立即停止,或者在停止前执行一些其他方法,这取决于线程自身的中断策略。
为什么不是调用interrupt()方法后,线程理解停止?因为线程中断的思想是基于:一个线程不应该由其他线程强制中断或停止,而是应该由线程自己自行停止的思想。如果一个线程调用另一个线程的interrupt()方法后,被中断线程如果立即停止的话,那么这会带来一些问题:如资源没有及时释放,数据库连接未关闭,数据丢失,甚至是死锁问题等等。这就是suspend和resume和stop方法过期的原因(它们都是抢占式的,interrupt是协作式的)。因此,调用interrupt()并不意味着立即停止目标线程正在进行的工作,而只是传递了请求中断的消息(即把中断标志设置为了true)。
中断策略
《Java并发编程实战》中说过:通常,中断是线程实习取消的最合理的方式。这正是因为中断是一种非常温和的关闭方法,不会带来负面影响。
因此中断最主要的作用就是取消一个任务,并且被中断的任务中应该实现自己的中断策略:规定线程如何解释某个中断请求---当发现中断请求时,应该做那些工作,那些单元是原子操作,以及以多快速度来响应中断。
interrupted()方法:测试当前线程的中断状态,并会重置当前线程的中断状态
interrupted()是Thread的静态方法:内部实现是调用的当前线程的isInterrupted(),并且会重置当前线程的中断状态。
当前线程未被中断:第一次调用interrupted()返回false,第二次依然返回false。
当前线程被中断:第一次调用interrupted()返回true,第二次返回false。(重置当前线程的中断状态)
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
isInterrupted()方法。
isInterrupted()是线程对象的实例方法,不会重置当前线程的中断状态
当前线程未被中断:第一次调用isInterrupted()返回false,第二次依然返回false。
当前线程被中断:第一次调用isInterrupted()返回true,第二次返回true。(不重置当前线程的中断状态)
@HotSpotIntrinsicCandidate private native boolean isInterrupted(boolean ClearInterrupted);
关于线程中断的两条原则:
1)除非你知道线程的中断策略,否则不应该中断它。
这条原则告诉我们,不应该直接调用Executer之类框架中线程的interrupt方法,应该利用诸如Future.cancel的方法来取消任务。
2)任务代码不该猜测中断对执行线程的含义。
这条原则告诉我们,一般代码遇在到InterruptedException异常时,不应该将其捕获后“吞掉”,而应该继续向上层代码抛出。