java线程之中断线程Interrupted用法

2018-05-18  本文已影响36人  小陈阿飞

中断线程-interrupt()

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

这里的 「stop」方法,和「resume」方法、「suspend」方法并称 Thread 三少,因为线程安全问题,都已经被 @Deprecated 了。。
当我们停止一个线程时,它会悄悄的把所持有的 monitor 锁释放了,此时,其他依赖锁的线程可能就会抢到锁执行。关键此时,当前 stop 的线程实际并没有处理完所有先决条件,可能这个时候就产生了诡异的问题,加班的日子可能就悄悄来了。

那你说 「Stop 不让用了,总得让我们有办法处理线程吧,哪怕通知他,打断他一下,让他停止」。

(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并不能中断线程执行。

首先我们看看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)*/  
强调一个知识:isInterrupted和interrupted区别

两者都是获取interrupt状态,但是interrupted方法在获取状态后,会重置状态。isInterrupted则不会重置状态。

上一篇 下一篇

猜你喜欢

热点阅读