java线程之中断线程Interrupted用法

中断线程-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则不会重置状态。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 一、线程的生命周期 线程状态转换图: 1、新建状态 用new关键字和Thread类或其子类建立一个线程对象后,该线...
    我是嘻哈大哥阅读 4,470评论 0 8
  • 单任务 单任务的特点是排队执行,也就是同步,就像再cmd输入一条命令后,必须等待这条命令执行完才可以执行下一条命令...
    Steven1997阅读 4,946评论 0 6
  • 一、认识多任务、多进程、单线程、多线程 要认识多线程就要从操作系统的原理说起。 以前古老的DOS操作系统(V 6....
    GT921阅读 4,597评论 0 3
  • 马平诗歌 2015-10-1 16:26 一瞬 那天的雨好大 我以为世界只剩下我一人 未料到还有你呀 在雨帘中...
    画画儿阅读 1,573评论 0 0
  • 之所以叫自娱自乐书单,是因为我想要推荐的书并不是特别晦涩艰深的,我曾试图逼自己坐在桌前一句句的读《史记》,读《国富...
    f8140a61cfbc阅读 4,296评论 8 10