interrupt、interrupted、isInterrupted的区别

转自 http://blog.csdn.net/budapest/article/details/6941802

中断线程 —— 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异常。

 //中断一个被阻塞的线程代码
class TestRunnable implements Runnable{
     public void run(){
          try{
	    Thread.sleep(1000000); //这个线程将被阻塞1000秒
       }catch(InterruptedException e){
	     e.printStackTrace();
                     //do more work and return.
          }
     }
}
public class TestDemo2{
      public static void main(String[] args) {
            Runnable tr=new TestRunnable();
            Thread th1=new Thread(tr);
            th1.start(); //开始执行分线程
        while(true){
	   th1.interrupt();  //中断这个分线程
        }
      }
}
/*运行结果:
   java.lang.InterruptedException: sleep interrupted
        at java.lang.Thread.sleep(Native Method)
        at TestRunnable.run(TestDemo2.java:4)
        at java.lang.Thread.run(Unknown Source)*/

* 如果线程被阻塞,它便不能核查共享变量,也就不能停止。这在许多情况下会发生,例如调用
* Object.wait()、ServerSocket.accept()和DatagramSocket.receive()时,他们都可能永
* 久的阻塞线程。即使发生超时,在超时期满之前持续等待也是不可行和不适当的,所以,要使
* 用某种机制使得线程更早地退出被阻塞的状态。很不幸运,不存在这样一种机制对所有的情况
* 都适用,但是,根据情况不同却可以使用特定的技术。使用Thread.interrupt()中断线程正
* 如Example1中所描述的,Thread.interrupt()方法不会中断一个正在运行的线程。这一方法
* 实际上完成的是,在线程受到阻塞时抛出一个中断信号,这样线程就得以退出阻塞的状态。更
* 确切的说,如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞,那么,
* 它将接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态。

----------------------------------------------------------------------------------------------------------------------------------

1、interrupt 
interrupt方法用于中断线程。调用该方法的线程的状态为将被置为"中断"状态。
注意:线程中断仅仅是置线程的中断状态位,不会停止线程。需要用户自己去监视线程的状态为并做处理。支持线程中断的方法(也就是线程中断后会抛出interruptedException的方法)就是在监视线程的中断状态,一旦线程的中断状态被置为“中断状态”,就会抛出中断异常。


2、interrupted 和 isInterrupted

首先看一下该方法的实现:
1 public static boolean interrupted () {
2      return currentThread().isInterrupted(true);
3 }
该方法就是直接调用当前线程的isInterrupted(true)方法。
然后再来看一下 isInterrupted的实现:
1 public boolean isInterrupted () {
2      return isInterrupted( false);
3 }
这两个方法有两个主要区别:
  1. interrupted 是作用于当前线程,isInterrupted 是作用于调用该方法的线程对象所对应的线程。(线程对象对应的线程不一定是当前运行的线程。例如我们可以在A线程中去调用B线程对象的isInterrupted方法。)
  2. 这两个方法最终都会调用同一个方法,只不过参数一个是true,一个是false;

第二个区别主要体现在调用的方法的参数上,让我们来看一看这个参数是什么含义

先来看一看被调用的方法 isInterrupted(boolean arg)的定义:
1 private native boolean isInterrupted( boolean ClearInterrupted);
原来这是一个本地方法,看不到源码。不过没关系,通过参数名我们就能知道,这个参数代表是否要清除状态位。

如果这个参数为true,说明返回线程的状态位后,要清掉原来的状态位(恢复成原来情况)。这个参数为false,就是直接返回线程的状态位。

这两个方法很好区分,只有当前线程才能清除自己的中断位(对应interrupted()方法)

 

 

是不是这样理解呢,
Thread.currentThread().interrupt(); 这个用于清除中断状态,这样下次调用Thread.interrupted()方法时就会一直返回为true,因为中断标志已经被恢复了。
而调用isInterrupted 只是简单的查询中断状态,不会对状态进行修改。

interrupt()是用来设置中断状态的。返回true说明中断状态被设置了而不是被清除了。我们调用sleep、wait等此类可中断(throw InterruptedException)方法时,一旦方法抛出InterruptedException,当前调用该方法的线程的中断状态就会被jvm自动清除了,就是说我们调用该线程的isInterrupted 方法时是返回false。如果你想保持中断状态,可以再次调用interrupt方法设置中断状态。这样做的原因是,java的中断并不是真正的中断线程,而只设置标志位(中断位)来通知用户。如果你捕获到中断异常,说明当前线程已经被中断,不需要继续保持中断位。
interrupted是静态方法,返回的是当前线程的中断状态。例如,如果当前线程被中断(没有抛出中断异常,否则中断状态就会被清除),你调用interrupted方法,第一次会返回true。然后,当前线程的中断状态被方法内部清除了。第二次调用时就会返回false。如果你刚开始一直调用isInterrupted,则会一直返回true,除非中间线程的中断状态被其他操作清除了。

猜你喜欢

转载自wuchangqing.iteye.com/blog/2365267