今天在看板桥人的Java实用系统指南一书的过程中,其中提出了一个使用
while
(!Thread.interrupted())代替while(true)语句,使得线程在执行错误时能够放弃对CPU独霸的方法,由于在项目中对线程
的编程比较少,因此就在网上查找了一下interrupt()方法的具体含义和用途,不查不知道,一查吓一跳,看来自己真应该好好补补了,在此转载一篇个
人认为讲解得比较好的文章,希望能帮助到大家
转自:http://blog.csdn.net/axman/archive/2005/12/26/562249.aspx
[线程的中断]
不客气地说,至少有一半人认为,线程的"中断"就是让线程停止.(
)
如果你也这么认为,那你对多线程编程还没有入门.
在java中,线程的中断(interrupt)只是改变了线程的中断状态,至于这个中断状态改变后带来的结果,那是无法确定的,有时它更是让停止中的线程继续执行的唯一手段.不但不是让线程停止运行,反而是继续执行线程的手段.
对于执行一般逻辑的线程,如果调用调用它的interrupt()方法,那么对这个线程没有任何影响,比如线程a正在执行:
while(条件) x ++;
这样的语句,如果其它线程调用a.interrupt();那么并不会影响a对象上运行的线程,如果在其它线程里测试a的中断状态它已经改变,但并不会停止这个线程的运行.
在一个线程对象上调用interrupt()方法,真正有影响的是wait,join,sleep方法,当然这三个方法包括它们的重载方法.
请注意:[上面这三个方法都会抛出InterruptedException],记住这句话,下面我会重复.
一个线程在调用interrupt()后,自己不会抛出InterruptedException异常,所以你看到interrupt()并没有抛出这个异常,所以我上面说如果线程a正在执行while(条件) x ++;
你调用a.interrupt();后线程会继续正常地执行下去.
但是,如果一个线程被调用了interrupt()后,它的状态是已中断的.这个状态对于正在执行wait,join,sleep的线程,却改变了线程的运行结果.
一.对于wait中等待notify/notifyAll唤醒的线程,其实这个线程已经"暂停"执行,因为它正在某一对象的休息室中,这时如果它的中断状
态被改变,那么它就会抛出异常.这个InterruptedException异常不是线程抛出的,而是wait方法,也就是对象的wait方法内部会不
断检查在此对象上休息的线程的状态,如果发现哪个线程的状态被置为已中断,则会抛出InterruptedException,意思就是这个线程不能再等
待了,其意义就等同于唤醒它了.
这里唯一的区别是,被notify/All唤醒的线程会继续执行wait下面的语句,而在wait中被中断的线程则将控制权交给了catch语句.一些正常的逻辑要被放到catch中来运行.
但有时这是唯一手段,比如一个线程a在某一对象b的wait中等待唤醒,其它线程必须获取到对象b的监视锁才能调用b.notify()[All],否则
你就无法唤醒线程a,但在任何线程中可以无条件地调用a.interrupt();来达到这个目的.只是唤醒后的逻辑你要放在catch中,当然同
notify/All一样,继续执行a线程的条件还是要等拿到b对象的监视锁.
二.对于sleep中的线程,如果你调用了Thread.sleep(一年);现在你后悔了,想让它早些醒过来,调用interrupt()方法就是唯一
手段,只有改变它的中断状态,让它从sleep中将控制权转到处理异常的catch语句中,然后再由catch中的处理转换到正常的逻辑.同样,地于
join中的线程你也可以这样处理.
对于一般介绍多线程模式的书上,他们会这样来介绍:当一个线程被中断后,在进入wait,sleep,join方法时会抛出异常.
是的,这一点也没有错,但是这有什么意义呢?如果你知道那个线程的状态已经处于中断状态,为什么还要让它进入这三个方法呢?当然有时是必须这么做的,但大
多数时候没有这么做的理由,所以我上面主要介绍了在已经调用这三个方法的线程上调用interrupt()方法让它中这本个方法的"暂停"状态中恢复过
来.这个恢复过来就可以包含两个目的:
一.[可以使线程继续执行],那就是在catch语句中招待醒来后的逻辑,或由catch语句
转回正常的逻辑.总之它是从wait,sleep,join的暂停状态活过来了.
二.[可以直接停止线程的运行],当然在catch中什么也不处理,或return,那么就完成
了当前线程的使命,可以使在上面"暂停"的状态中立即真正的"停止".
中断线程
有了上面的[线程的中断],我们就好进行如何[中断线程]了.这绝对不是玩一个文字游戏.
是因为"线程的中断"并不能保证"中断线程",所以我要特别地分为两节来说明.
这里说的"中断线程"意思是"停止线程",而为什么不用"停止线程"这个说法呢?
因为线程有一个明确的stop方法,但它是反对使用的,所以请大家记住,在java中以后不要提停止线程这个说法,忘记它!
但是,作为介绍线程知识的我,我仍然要告诉你为什么不用"停止线程"的理由.
[停止线程]
当在一个线程对象上调用stop()方法时,这个线程对
象所运行的线程就会立即停止,并抛出特殊的ThreadDeath()异常.这里的"立即"因为太"立即"了,就象一个正在摆弄自己的玩具的孩子,听到大
人说快去睡觉去,就放着满地的玩具立即睡觉去了.这样的孩子是不乖的.
假如一个线程正在执行:
-
synchronized
void
{
-
x = 3
;
-
y = 4
;
-
}
synchronized void {
x = 3;
y = 4;
}
由于方法是同步的,多个线程访问时总能保证x,y被同时赋值,而如果
一个线程正在执行到x = 3;时,被调用了
stop()方法,即使在同步块中,它也干脆地stop了,这样就产生了不完整的残废数据.而多线程编程中最最基础的条件要保证数据的完整性,所以请忘记
线程的stop方法,以后我们再也不要说"停止线程"了.
如何才能"结束"一个线程?
[中断线程]
结束一个线程,我们要分析线程的运行情况.也就是线程正在干什么.如果那个孩子什么事也没干,那就让他立即去睡觉.而如果那个孩子正在摆弄他的玩具,我们就要让它把玩具收拾好再睡觉.
所以一个线程从运行到真正的结束,应该有三个阶段:
1.正常运行.
2.处理结束前的工作,也就是准备结束.
3.结束退出.
在我的JDBC专栏中我N次提醒在一个SQL逻辑结束后,无论如何要保证关闭Connnection那就是在finally从句中进行.同样,线程在结束前的工作应该在finally中来保证线程退出前一定执行:
try{
正在逻辑
}catch(){}
finally{
清理工作
}
那么如何让一个线程结束呢?既然不能调用stop,可用的只的interrupt()方法.但interrupt()方法只是改变了线程的运行状态,如何让它退出运行?
对于一般逻辑,只要线程状态为已经中断,我们就可以让它退出,所以这样的语句可以保证线程在中断后就能结束运行:
while(!isInterrupted()){
正常逻辑
}
这样如果这个线程被调用interrupt()方法,isInterrupted()为true,就会退出运行.但是如果线程正在执行wait,sleep,join方法,你调用interrupt()方法,这个逻辑就不完全了.
如果一个有经验的程序员来处理线程的运行的结束:
public void run(){
try{
while(!isInterrupted()){
正常工作
}
}
catch(Exception e){
return;
}
finally{
清理工作
}
}
我们看到,如果线程执行一般逻辑在调用innterrupt后.isInterrupted()为true,退出循环后执行清理工作后结束,即使线程正在wait,sleep,join,也会抛出异常执行清理工作后退出.
这看起来非常好,线程完全按最我们设定的思路在工作.但是,并不是每个程序员都有这种认识,如果他聪明的自己处理异常会如何?事实上很多或大多数程序员会这样处理:
public void run(){
while(!isInterrupted()){
try{
正常工作
}catch(Exception e){
//nothing
}
finally{
}
}
}
想一想,如果一个正在sleep的线程,在调用interrupt后,会如何?
wait
方法检查到isInterrupted()为true,抛出异常,而你又没有处理.而一个抛出了InterruptedException的线程的状态马
上就会被置为非中断状态,如果catch语句没有处理异常,则下一次循环中isInterrupted()为false,线程会继续执行,可能你N次抛出
异常,也无法让线程停止.
那么如何能确保线程真正停止?
在线程同步的时候我们有一个叫"二次惰性检测"(double check),能在提高效率的基础上又确保线程真正中同步控制中.
那么我把线程正确退出的方法称为"双重安全退出",即不以isInterrupted()为循环条件.而以一个标记作为循环条件:
class MyThread extend Thread{
private boolean isInterrupted = false;//这一句以后要修改
public void interrupt(){
isInterrupted = true;
super.interrupt();
}
public void run(){
while(!isInterrupted){
try{
正常工作
}catch(Exception e){
//nothing
}
finally{
}
}
}
}
试试这段程序,可以正确工作吗?
对于这段程序仍然还有很多可说的地方,先到这里吧.
分享到:
相关推荐
在嵌入式系统开发中,中断(Interrupt)是硬件与软件之间进行通信的重要机制,它使得微控制器能够及时响应外部事件,而无需持续轮询。本文将深入探讨使用MPLABX集成开发环境和XC8编译器进行中断处理的例子。 标题...
### 解释 void timer0() interrupt 1 using 2 在探讨`void timer0() interrupt 1 using 2`这一表达式之前,我们首先需要理解它所处的上下文——80C51单片机系统及其编程环境。80C51是一款广泛应用于嵌入式系统的微...
在IT领域,"com interrupt void interrupt 4 using 3" 这个描述涉及到的是中断服务子程序(Interrupt Service Routine, ISR),这是在微处理器系统中处理外部硬件事件的一种机制。这里的“com”可能指的是串行通信...
### ARM Generic Interrupt Controller (GIC) Architecture Specification #### 概述 ARM Generic Interrupt Controller (GIC) 是一种中断控制器架构规范,旨在为基于ARM架构的操作系统提供通用且灵活的中断管理...
早期的PC系统采用传统的可编程中断控制器(PIC, Programmable Interrupt Controller)来管理中断请求。在最初的IBM PC设计中,有两个8259A PIC芯片共同工作,负责处理中断请求。 - **主PIC**: 负责管理IRQ0至IRQ7共8...
### Polyspace与中断处理:让Polyspace认识Interrupt #### 一、引言 在嵌入式系统开发过程中,中断处理是不可或缺的一部分。中断可以让系统在特定条件下响应外部事件,从而实现高效的实时处理能力。然而,在进行...
《Ralf Brown's Interrupt List》是计算机领域内一本非常重要的参考资源,主要涵盖了微处理器和其他硬件设备中断的详细信息。这个列表由Ralf Brown维护,是程序员、系统工程师和硬件爱好者在处理中断相关问题时不可...
处理器响应中断后,会保存当前任务的状态,跳转到预先定义的中断服务程序(ISR,Interrupt Service Routine)执行相应的操作,处理完事件后再恢复先前的任务,这就是中断的上下文切换。 在基于DSP的系统中,中断...
文档首先介绍了在nRF51822中引入的Task和Event机制,以及它们与Interrupt(中断)的关系。接着详细阐述了中断的概念、中断的触发机制、中断源代码的编写、以及如何通过代码样例来实现中断接收。以下详细解释了文档中...
文档提供了ARM® Generic Interrupt Controller的架构规范,介绍了GIC架构3.0和4.0版本的详细信息,其中包含了一些在先前版本2.0中已经发布的资料。此外,文档还涉及到版权和知识产权的声明,明确指出该文档受版权...
《Ralf Brown's Interrupt List》是DOS操作系统中不可或缺的一个技术资源,由Ralf Brown编纂,详尽地列举了DOS以及IBM PC兼容机上的中断服务,包括BIOS(基本输入输出系统)和DOS中断。这个列表是程序员、系统开发者...
程序名称:interrupt.asm 程序说明:74HC595驱动数码管动态显示例,通过按键触发外部中断,P3.2进行计数,P3.3清零,实验箱上完成 算法说明:由两片74HC595芯片分别驱动段和位,数码管动态扫描显示:修改延时子...
Detection of Excessive Interrupt Disablement - a new feature which can detect a period of excessive interrupt disablement on a CPU, and create an error log record to report it. This allows you to know...
ARM Generic Interrupt Controller (ARM GIC控制器)V2.0 ARM Generic Interrupt Controller (ARM GIC控制器)是ARM公司推出的一个通用中断控制器架构规范,用于实现高效的中断处理。该规范旨在提供一个灵活的中断...
《Arm CoreLink GIC-600 Generic Interrupt Controller 技术参考手册》是关于ARMv8架构下中断控制器GIC-600的详细指南,由ARM Limited或其关联公司版权所有。该手册覆盖了从r1p6版本的多个发布迭代,提供了控制器的...
在计算机科学领域,中断服务程序(Interrupt Service Routines, ISR)是一种特殊类型的程序,它们被设计用于处理来自硬件设备的中断请求。这些请求可能由外部事件触发,如键盘按键、定时器超时或磁盘读写完成等。在...
The Generic Interrupt Controller (GIC) architecture defines: • the architectural requirements for handling all interrupt sources for any processor connected to a GIC • a common interrupt controller ...
微机接口课程实验interrupt.asm
### Open Firmware Recommended Practice: Interrupt Mapping 版本 0.9 #### 1. 概述与背景 在计算机系统中,中断(Interrupt)是硬件设备与操作系统之间进行通信的重要方式之一。当一个设备需要处理紧急任务时,...