美文网首页
java线程之中断线程Interrupted用法

java线程之中断线程Interrupted用法

作者: 小陈阿飞 | 来源:发表于2018-05-18 14:28 被阅读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则不会重置状态。

    相关文章

      网友评论

          本文标题:java线程之中断线程Interrupted用法

          本文链接:https://www.haomeiwen.com/subject/dljgdftx.html