`
tommy14101
  • 浏览: 4601 次
  • 性别: Icon_minigender_1
  • 来自: 大连
最近访客 更多访客>>
社区版块
存档分类
最新评论

interrupt

阅读更多

今天在看板桥人的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()异常.这里的"立即"因为太"立即"了,就象一个正在摆弄自己的玩具的孩子,听到大 人说快去睡觉去,就放着满地的玩具立即睡觉去了.这样的孩子是不乖的.

假如一个线程正在执行:

Java代码  收藏代码
  1. synchronized   void  {  
  2.    x = 3 ;  
  3.    y = 4 ;  
  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.X_interrupt_

    在嵌入式系统开发中,中断(Interrupt)是硬件与软件之间进行通信的重要机制,它使得微控制器能够及时响应外部事件,而无需持续轮询。本文将深入探讨使用MPLABX集成开发环境和XC8编译器进行中断处理的例子。 标题...

    解释 void timer0() interrupt 1 using 2

    ### 解释 void timer0() interrupt 1 using 2 在探讨`void timer0() interrupt 1 using 2`这一表达式之前,我们首先需要理解它所处的上下文——80C51单片机系统及其编程环境。80C51是一款广泛应用于嵌入式系统的微...

    com interrupt void interrupt 4 using 3

    在IT领域,"com interrupt void interrupt 4 using 3" 这个描述涉及到的是中断服务子程序(Interrupt Service Routine, ISR),这是在微处理器系统中处理外部硬件事件的一种机制。这里的“com”可能指的是串行通信...

    ARM Generic Interrupt Spec

    ### ARM Generic Interrupt Controller (GIC) Architecture Specification #### 概述 ARM Generic Interrupt Controller (GIC) 是一种中断控制器架构规范,旨在为基于ARM架构的操作系统提供通用且灵活的中断管理...

    Interrupt in Linux(硬件篇).pdf

    早期的PC系统采用传统的可编程中断控制器(PIC, Programmable Interrupt Controller)来管理中断请求。在最初的IBM PC设计中,有两个8259A PIC芯片共同工作,负责处理中断请求。 - **主PIC**: 负责管理IRQ0至IRQ7共8...

    Polyspace不认识Interrupt,肿么办?

    ### Polyspace与中断处理:让Polyspace认识Interrupt #### 一、引言 在嵌入式系统开发过程中,中断处理是不可或缺的一部分。中断可以让系统在特定条件下响应外部事件,从而实现高效的实时处理能力。然而,在进行...

    Ralf Brown's Interrupt List

    《Ralf Brown's Interrupt List》是计算机领域内一本非常重要的参考资源,主要涵盖了微处理器和其他硬件设备中断的详细信息。这个列表由Ralf Brown维护,是程序员、系统工程师和硬件爱好者在处理中断相关问题时不可...

    interrupt中断

    处理器响应中断后,会保存当前任务的状态,跳转到预先定义的中断服务程序(ISR,Interrupt Service Routine)执行相应的操作,处理完事件后再恢复先前的任务,这就是中断的上下文切换。 在基于DSP的系统中,中断...

    电子-7interrupt.pdf

    文档首先介绍了在nRF51822中引入的Task和Event机制,以及它们与Interrupt(中断)的关系。接着详细阐述了中断的概念、中断的触发机制、中断源代码的编写、以及如何通过代码样例来实现中断接收。以下详细解释了文档中...

    ARM Generic Interrupt Controller Architecture Specification

    文档提供了ARM® Generic Interrupt Controller的架构规范,介绍了GIC架构3.0和4.0版本的详细信息,其中包含了一些在先前版本2.0中已经发布的资料。此外,文档还涉及到版权和知识产权的声明,明确指出该文档受版权...

    Ralf Brown's Interrupt List(中断大全)

    《Ralf Brown's Interrupt List》是DOS操作系统中不可或缺的一个技术资源,由Ralf Brown编纂,详尽地列举了DOS以及IBM PC兼容机上的中断服务,包括BIOS(基本输入输出系统)和DOS中断。这个列表是程序员、系统开发者...

    interrupt_asm.zip

    程序名称:interrupt.asm 程序说明:74HC595驱动数码管动态显示例,通过按键触发外部中断,P3.2进行计数,P3.3清零,实验箱上完成 算法说明:由两片74HC595芯片分别驱动段和位,数码管动态扫描显示:修改延时子...

    Detection of Excessive Interrupt Disablement

    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.pdf

    ARM Generic Interrupt Controller (ARM GIC控制器)V2.0 ARM Generic Interrupt Controller (ARM GIC控制器)是ARM公司推出的一个通用中断控制器架构规范,用于实现高效的中断处理。该规范旨在提供一个灵活的中断...

    gic600_generic_interrupt_controller_reference_manual.pdf

    《Arm CoreLink GIC-600 Generic Interrupt Controller 技术参考手册》是关于ARMv8架构下中断控制器GIC-600的详细指南,由ARM Limited或其关联公司版权所有。该手册覆盖了从r1p6版本的多个发布迭代,提供了控制器的...

    Interrupt Services DOS, BIOS, EMS and Mouse.pdf

    在计算机科学领域,中断服务程序(Interrupt Service Routines, ISR)是一种特殊类型的程序,它们被设计用于处理来自硬件设备的中断请求。这些请求可能由外部事件触发,如键盘按键、定时器超时或磁盘读写完成等。在...

    Generic Interrupt Controller 2.0

    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

    微机接口课程实验interrupt.asm

    Open Firmware Recommended Practice: Interrupt Mapping Version 0.9

    ### Open Firmware Recommended Practice: Interrupt Mapping 版本 0.9 #### 1. 概述与背景 在计算机系统中,中断(Interrupt)是硬件设备与操作系统之间进行通信的重要方式之一。当一个设备需要处理紧急任务时,...

Global site tag (gtag.js) - Google Analytics