Java 并发Android开发经验谈Android开发

Java线程Thread之interrupt中断解析

2018-01-25  本文已影响100人  Ihesong

这一篇我们说说Java线程Thread的interrupt中断机制。

interrupt之中断状态标记

interrupt中断机制中有如下方法:

public class InterruptTest {
   //这里用来打印消耗的时间
  private static long time = 0;
  private static void resetTime(){
    time = System.currentTimeMillis();
  }
  private static void printContent(String content){
    System.out.println(content + "     时间:" + (System.currentTimeMillis() - time));
  }

  public static void main(String[] args) {

    test1();

  }

  private static void test1(){

    Thread1 thread1 = new Thread1();
    thread1.start();

    //延时3秒后interrupt中断
    try {
      Thread.sleep(3000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }

    thread1.interrupt();
    printContent("执行中断");

  }

  private static class Thread1 extends Thread{

    @Override public void run() {

      resetTime();

      int num = 0;
      while (true){
        if(isInterrupted()){
          printContent("当前线程 isInterrupted");
          break;
        }

        num++;

        if(num % 100 == 0){
          printContent("num : " + num);
        }
      }

    }

  }

}

以上代码是开启一个Thread1线程,在Thread1线程的while循环中不断对num加1,每到100的倍数打印一次(防止打印太快)。然后主线程在sleep了3000毫秒后,调用Thread1线程的interrupt方法。那么我们看看输出结果:

intterupt中断

可以看到,在耗时3000毫秒左右,也就是主线程sleep之后执行thread1.interrupt();后,Thread1线程停止了,而Thread1线程的停止是因为while循环中的isInterrupted方法返回了true,所以break退出了while循环,也就是说interrupt和isInterrupted在这里起到的作用就相当于setXX和getXX的作用,维护着一个boolean变量。

interrupt之中断异常处理

当然interrupt机制并不仅仅是一个中断状态位的变化和检测,它还可以进行中断异常的处理。我们知道Thread.sleep()方法需要捕获中断异常,那接下来我们往其中添加一个sleep延时试试

  while (true){
    if(isInterrupted()){
      printContent("当前线程 isInterrupted");
      break;
    }

    num++;
    
    //sleep一下
    try {
      Thread.sleep(1);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }

    if(num % 100 == 0){
      printContent("num : " + num);
    }
  }

我们再看看输出结果:

intterupt中断

这里我们会发现,sleep睡眠之后,输出的num值明显小了好多(没睡眠时num都达到10亿的大小了,看来CPU执行简单运算还是非常快的),哈哈,不过这不是重点,重点是是看到输出了一个异常,还有就是输出异常后,isInterrupted输出返回false,Thread1线程又继续执行下去了,并没有退出while循环。那么这是为什么呢?我们只是加了一个sleep睡眠而已。

如果Thread1线程中有执行需要捕获InterruptedException异常的操作,比如Thread的sleep,join方法,Object的wait,Condition的await等,它是强制需要捕获InterruptedException异常的,那么当thread1.interrupt方法调用之后,它会给thread1线程抛出一个InterruptedException异常,那么在while循环中,就能捕获到这个异常然后这个异常抛出之后,又会马上将线程中断标识重置为false,因此在下次的while循环中判断isInterrupted时,它是false,也就不会break,然后while循环会一直执行下去。

因此interrupt()方法会根据thread线程中的run方法里是否有必须捕获InterruptedException异常的代码,而做出不同操作:

interrupt的应用场景

通常interrupt适用于在线程执行中的循环标记判断,例如

while(!isInterrupted()){
    ...
}

但是如果在本次循环中出现阻塞了,那么线程就无法判断下次的isInterrupted标记,那么即便调用了interrupt()方法也无法退出循环,也就无法退出线程。例如
}

while(!isInterrupted()){
    ...
    
    while(true){
        //线程卡在这里了,则无法响应interrupte机制了
    }
}

这样的话,interrupt就没辙了,线程会一直执行下去,不会被中断停止。

测试例子查看 我的GitHub--JavaTest

上一篇下一篇

猜你喜欢

热点阅读