【解惑】 中断线程Interrupted的用处

转载自:http://hxraid.iteye.com/blog/429005

 

★ 线程状态

       Java虚拟机将线程运行过程分成四种状态 。 (1) New 新生;(2) Runnable 可运行;(3) Blocked 阻塞;(4) Dead 死亡。

      值得注意的是: 线程的可运行状态并不代表线程一定在运行(runnable != running ) 。 大家都知道:所有现代桌面和服务器操作系统都使用了抢占式的线程调度策略。一旦线程开始执行,并不是总是保持持续运行状态的。当系统分给它的时间片(非常小的运行时间单位)用完以后,不管程序有没有执行完,线程被强制放弃CPU,进入就绪状态,直到下次被调度后开始继续执行。也就是说, Runnable可运行状态的线程处于两种可能的情况下:(1)占用CPU运行中,(2)等待调度的就绪状态。 这里要声明一下:处于等待调度的就绪状态线程和处于阻塞的线程是完全不同的。就绪的线程是因为时间片用完而放弃CPU,其随时都有可能再次获得CPU而运行,这一切取决于分时OS的线程调度策略。

       在很多操作系统的专业术语中,这种因时间片用完而被剥夺CPU的情况我们叫做线程中断。注意这和我们下面要将得中断线程是两个完全不同的概念。事实上,我们不可能通过应用程序来控制CPU的线程中断,除非我们能够自由调用OS的内核。


中断线程 —— interrupt()

       一个正在运行的线程除了正常的时间片中断之外,能否被其他线程控制?或者说其他线程能否让指定线程放弃CPU或者提前结束运行? 除了线程同步机制之外,还有两种方法:
       (1) Thread.stop(), Thread.suspend(), Thread.resume() 和Runtime.runFinalizersOnExit() 这些终止线程运行的方法 。这些方法已经被废弃,使用它们是极端不安全的。
       (2) Thread.interrupt() 方法是很好的选择。但是使用的时候我们必须好好理解一下它的用处。

//无法中断正在运行的线程代码    
class TestRunnable implements Runnable{    
     public void run(){    
           while(true)    
           {    
                 System.out.println( "Thread is running..." );    
                 long time = System.currentTimeMillis();//去系统时间的毫秒数    
           while((System.currentTimeMillis()-time < 1000)) {    
                  //程序循环1秒钟,不同于sleep(1000)会阻塞进程。    
            }    
              }    
       }    
}    
public class ThreadDemo{    
         public static void main(String[] args){    
               Runnable r=new TestRunnable();    
               Thread th1=new Thread(r);    
               th1.start();    
               th1.interrupt();             
        }    
}    
/运行结果:一秒钟打印一次Thread is running...。程序没有终止的任何迹象  

 

    上面的代码说明interrupt()并没有中断一个正在运行的线程,或者说让一个running中的线程放弃CPU。那么interrupt到底中断什么。

       首先我们看看interrupt究竟在干什么。

       当我们调用th1.interrput()的时候,线程th1的中断状态(interrupted status) 会被置位。我们可以通过Thread.currentThread().isInterrupted() 来检查这个布尔型的中断状态。

        在Core Java中有这样一句话:"没有任何语言方面的需求要求一个被中断的程序应该终止。中断一个线程只是为了引起该线程的注意,被中断线程可以决定如何应对中断"。好好体会这句话的含义,看看下面的代码:

//Interrupted的经典使用代码  
 public void run(){  
         try{  
              ....  
              while(!Thread.currentThread().isInterrupted()&& more work to do){  
                     // do more work;  
              }  
         }catch(InterruptedException e){  
                     // thread was interrupted during sleep or wait  
         }  
         finally{  
                    // cleanup, if required  
         }  
 }  

        很显然,在上面代码中,while循环有一个决定因素就是需要不停的检查自己的中断状态。当外部线程调用该线程的interrupt 时,使得中断状态置位。这是该线程将终止循环,不在执行循环中的do more work了。

       这说明: interrupt中断的是线程的某一部分业务逻辑,前提是线程需要检查自己的中断状态(isInterrupted())。

       但是当th1被阻塞的时候,比如被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞时。调用它的interrput()方法。可想而知,没有占用CPU运行的线程是不可能给自己的中断状态置位的。这就会产生一个InterruptedException异常。

Java代码 复制代码  收藏代码
  1.  //中断一个被阻塞的线程代码  
  2. class TestRunnable implements Runnable{  
  3.      public void run(){  
  4.           try{  
  5.         Thread.sleep(1000000); //这个线程将被阻塞1000秒  
  6.        }catch(InterruptedException e){  
  7.          e.printStackTrace();  
  8.                      //do more work and return.  
  9.           }  
  10.      }  
  11. }  
  12. public class TestDemo2{  
  13.       public static void main(String[] args) {  
  14.             Runnable tr=new TestRunnable();  
  15.             Thread th1=new Thread(tr);  
  16.             th1.start(); //开始执行分线程  
  17.         while(true){  
  18.        th1.interrupt();  //中断这个分线程  
  19.         }  
  20.       }  
  21. }  
  22. /*运行结果: 
  23.    java.lang.InterruptedException: sleep interrupted 
  24.         at java.lang.Thread.sleep(Native Method) 
  25.         at TestRunnable.run(TestDemo2.java:4) 
  26.         at java.lang.Thread.run(Unknown Source)*/  

 

 

目前理解是其他线程(也可以是当前线程)可以给当前线程发出一个interrupt信号,当前线程使用isInterrupted 判断是否收到这个信号,若收到信号,则当前线程进行相应处理。若当前线程处于被阻塞状态则抛出异常(上面有讲到);若当前线程正在执行,且不使用isInterrupte判断是否有中断信号,则这个信号不会对当前线程有任何影响。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值