java线程中断的本质,简单的设计思想(转)

    本文部分内容转自:http://blog.csdn.net/dlite/article/details/4218105,原文作者为:DLite。仅部分摘录。

    一直以来,用过很多线程的应用,最经常使用的就是开启一个线程,然后就不管之,任其运行。或者运行成功,或者运行失败,都跟主线程无关。稍微用得多一点的就是使用对象的wait,再配合线程之间的调度,当线程需要中断时,直接中断其,然后被中断的线程抛出一个中断异常,自然地被中止运行了(因为没有捕获异常,被中断线程方法自然停止运行)。

    但是长久地来看,并没有了解线程中断的实质。从简单上来讲,中断一个线程,可以理解为中断这个线程的运行,就像使用thread.stop方法所运行的一样;并且实际运行效果也是这样,因为线程抛出了异常,而我们没捕获,则线程自然被中断,听起来中断一个线程就和停止线程运行一个效果。但实际上,这是两个完全不一样的工作方式。
    所谓的线程停止,是指这个线程已经不再运行了;而中断,则是指线程由于某种原因被外力(或自身)要求停止不再运行,但线程仍然拥有是否继续运行(或停止运行)的权利,关键在于线程如何处理这个中断的动作。简单一点理解就是,线程中断,只是向线程发送了一个标记,表示这个线程应该中断了,但如何停止运行是由线程自身或处理中断的行为所决定的。
        以下为引用内容:

    JVM内部确实为每个线程维护了一个中断标记。
    通常情况下,调用线程的interrupt方法,并不能立即引发中断,只是设置了JVM内部的中断标记。因此,通过检查中断标记,应用程序可以做一些特殊操作,也可以完全忽略中断。
    你可能想,如果JVM只提供了这种简陋的中断机制,那和应用程序自己定义中断变量并轮询的方法相比,基本也没有什么优势。
    JVM内部中断变量的主要优势,就是对于某些情况,提供了模拟自动“中断陷入”的机制。
    在执行涉及线程调度的阻塞调用时(例如wait、sleep和join),如果发生中断,被阻塞线程会“尽可能快的”抛出InterruptedException。
    所谓“尽可能快”,我猜测JVM就是在线程调度调度的间隙检查中断变量,速度取决于JVM的实现和硬件的性能。

    另外,有jdk源代码为证,下方法为thread的interrupt方法:

    public void interrupt() {
	if (this != Thread.currentThread())
	    checkAccess();

	synchronized (blockerLock) {
	    Interruptible b = blocker;
	    if (b != null) {
//以下此方法,包括调用2,均只设置一个中断标记,下一行的英文注解为原jdk注解
		interrupt0();		// Just to set the interrupt flag
		b.interrupt();
		return;
	    }
	}
	interrupt0();//调用2
    }

    所以,线程中断就是为指定的线程设定一个中断变量,然后当被操作的线程接收到这个变量之后,就努力地抛出一个中断异常出来。由于在一般情况下,我们没有catch这个异常,所以,线程被自然地异常退出了,而且不会影响到主线程。
    在正式地线程调试中,肯定需要对线程的中断行为,定制不同的处理方式,比如安全地释放资源,然后安全的退出等。

    既然有了这个中断的标记,那么肯定有读取这个标记的相应方法,即以下几个方法:

//设置中断标记
        public void interrupt() { ... }  
        //获取中断标记的值
        public boolean isInterrupted() { ... }
        //清除中断标记,并返回上一次中断标记的值
        public static boolean interrupted() { ... }   

    这上面的几个方法,有读取中断标记的,有读取中断标记并清除标记的,也有再次设置中断标记的。
    在一个线程在运行当中时(特别是在线程内部),我们可以通过isInterrupted方法,查询这个线程是否已经被中断了。如果被中断了,则可以进行相应的操作。
    当一个中断异常,抛出之后,它的中断标记即已经被清除,所以如果我们调用普通的isInterrupted方法时,将返回false。如果需要让上层的处理器知道此线程已经被中断了,我们需要再次调用interrupt方法来设置中断状态,并再次往上层抛出中断异常即可。

    总结:线程的中断本质就是一个中断标记和中断异常的配合,当设置中断标记时,异常被抛出。如果未捕获异常,线程被以异常的方式结束运行。如果捕获异常,则按照具体的情况决定如何运行线程(是结束还是结束)。异常是天生的以另一种方式结束程序的方式,而中断标记则有效地利用了这一点,并且从程序运行层面欺骗了使用它的人。

转载请标明出处:i flym
本文地址:https://www.iflym.com/index.php/code/201108090001.html

相关文章:

作者: flym

I am flym,the master of the site:)

发表评论

邮箱地址不会被公开。 必填项已用*标注