浅谈Java线程Thread之interrupt中断解析

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

中断线程

线程的thread.interrupt()方法是中断线程,将会设置该线程的中断状态位,即设置为true,中断的结果线程是死亡、还是等待新的任务或是继续运行至下一步,就取决于这个程序本身。线程会不时地检测这个中断标示位,以判断线程是否应该被中断(中断标示值是否为true)。它并不像stop方法那样会中断一个正在运行的线程。

判断线程是否被中断

判断某个线程是否已被发送过中断请求,请使用Thread.currentThread().isInterrupted()方法(因为它将线程中断标示位设置为true后,不会立刻清除中断标示位,即不会将中断标设置为false),而不要使用thread.interrupted()(该方法调用后会将中断标示位清除,即重新设置为false)方法来判断,下面是线程在循环中时的中断方式:

while(!Thread.currentThread().isInterrupted() && more work to do){
 do more work
}

interrupt之中断状态标记

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

  1. Thread.interrupt(),设置当前中断标记为true(类似属性的set方法)
  2. Thread.isInterrupted(),检测当前的中断标记(类似属性的get方法)
  3. Thread.interrupted(),检测当前的中断标记,然后重置中断标记为false(类似属性的get方法+set方法)

因此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异常的代码,而做出不同操作:

  1. 如果没有必须捕获InterruptedException异常的代码(比如Thread.sleep()),则isInterrupted()会返回true,此时可以在isInterrupted的判断中处理中断变化。
  2. 如果有必须捕获InterruptedException异常的代码(比如Thread.sleep()),则会抛出InterruptedException异常,并进行捕获,同时重置isInterrupted为false,此时得在异常捕获中处理中断变化。

interrupt的应用场景

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

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

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

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

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

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • JAVA多线程之中断机制stop()、interrupted()、isInterrupted()

    一,介绍 本文记录JAVA多线程中的中断机制的一些知识点.主要是stop方法.interrupted()与isInterrupted()方法的区别,并从源代码的实现上进行简单分析. JAVA中有3种方式可以终止正在运行的线程 ①线程正常退出,即run()方法执行完毕了 ②使用Thread类中的stop()方法强行终止线程.但stop()方法已经过期了,不推荐使用 ③使用中断机制 线程正常退出没有什么东东,中断机制下面详细介绍,先看下stop()方法的源代码,关键是源代码上的注释.它解释了为什么s

  • Java中断一个线程操作示例

    本文实例讲述了Java中断一个线程操作.分享给大家供大家参考,具体如下: 一 点睛 中断一个线程,意味着该线程在完成任务之前,停止它正在进行的一切当前的操作. 有三个比较常用的函数: interrupt():一个正在运行的A线程,可以调用B线程对应的interrupt方法来中断线程B.这个方法的核心功能是,将线程B的中断标识位属性设置为true. isInterrupted():通过该方法判断某个线程是否处于中断状态. interrupted():这是一个静态方法,用来获取当前线程的中断状态,并

  • java线程阻塞中断与LockSupport使用介绍

    上周五和周末,工作忙里偷闲,在看java cocurrent中也顺便再温故了一下Thread.interrupt和java 5之后的LockSupport的实现. 在介绍之前,先抛几个问题. Thread.interrupt()方法和InterruptedException异常的关系?是由interrupt触发产生了InterruptedException异常? Thread.interrupt()会中断线程什么状态的工作? RUNNING or BLOCKING? 一般Thread编程需要关注

  • Java多线程之中断线程(Interrupt)的使用详解

    interrupt方法 interrupt字面上是中断的意思,但在Java里Thread.interrupt()方法实际上通过某种方式通知线程,并不会直接中止该线程.具体做什么事情由写代码的人决定,通常我们会中止该线程. 如果线程在调用Object类的wait().wait(long)或wait(long, int)方法,或者该类的 join() .join(long) .join(long, int) .sleep(long) 或 sleep(long, int) 方法过程中受阻,则其中断状态

  • 浅析Java线程的中断机制

    线程中断机制提供了一种方法,用于将线程从阻塞等待中唤醒,尝试打断目标线程的现有处理流程,使之响应新的命令.Java 留给开发者这一自由,我们应当予以善用. 今天我们聊聊 Java 线程的中断机制. 线程中断机制提供了一种方法,有两种常见用途: 将线程从阻塞等待中唤醒,并作出相应的"受控中断"处理. 尝试告知目标线程:请打断现有处理流程,响应新的命令. 以第一种用途为例,请看以下代码: synchronized (lock) { try { while (!check()) { lock

  • 详解Java多线程编程中线程的启动、中断或终止操作

    线程启动: 1.start() 和 run()的区别说明 start() : 它的作用是启动一个新线程,新线程会执行相应的run()方法.start()不能被重复调用. run() : run()就和普通的成员方法一样,可以被重复调用.单独调用run()的话,会在当前线程中执行run(),而并不会启动新线程! 下面以代码来进行说明. class MyThread extends Thread{ public void run(){ ... } }; MyThread mythread = new

  • Java多线程中断机制三种方法及示例

    概述 之前讲解Thread类中方法的时候,interrupt().interrupted().isInterrupted()三个方法没有讲得很清楚,只是提了一下.现在把这三个方法同一放到这里来讲,因为这三个方法都涉及到多线程的一个知识点----中断机制. Java没有提供一种安全.直接的方法来停止某个线程,而是提供了中断机制.中断机制是一种协作机制,也就是说通过中断并不能直接终止另一个线程,而需要被中断的线程自己处理.有个例子举个蛮好,就像父母叮嘱出门在外的子女要注意身体一样,父母说了,但是子女

  • 详解Java线程中断知识点

    下面的这断代码大家应该再熟悉不过了,线程休眠需要捕获或者抛出线程中断异常,也就是你在睡觉的时候突然有个人冲进来把你吵醒了. try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } 此时线程被打断后,代码会继续运行或者抛出异常结束运行,这并不是我们需要的中断线程的作用. 到底是什么是线程中断? 线程中断即线程运行过程中被其他线程给打断了,它与 stop 最大的区别是:stop 是由系统强

  • Java检测线程中断状态的方法示例

    本文实例讲述了Java检测线程中断状态的方法.分享给大家供大家参考,具体如下: 一 代码 public class InterruptCheck { public static void main( String[] args ) throws Exception { // sleepThread不停尝试睡眠 Thread sleepThread = new Thread(new SleepRunner(), "SleepThread"); sleepThread.setDaemon(

  • 深入Java线程中断的本质与编程原则的概述

    在历史上,Java试图提供过抢占式限制中断,但问题多多,例如前文介绍的已被废弃的Thread.stop.Thread.suspend和 Thread.resume等.另一方面,出于Java应用代码的健壮性的考虑,降低了编程门槛,减少不清楚底层机制的程序员无意破坏系统的概率. 如今,Java的线程调度不提供抢占式中断,而采用协作式的中断.其实,协作式的中断,原理很简单,就是轮询某个表示中断的标记,我们在任何普通代码的中都可以实现. 例如下面的代码:    volatile bool isInter

  • Java中断线程的方法

    使用interrupt()中断线程 当一个线程运行时,另一个线程可以调用对应的Thread对象的interrupt()方法来中断它,该方法只是在目标线程中设置一个标志,表示它已经被中断,并立即返回.这里需要注意的是,如果只是单纯的调用interrupt()方法,线程并没有实际被中断,会继续往下执行. 下面一段代码演示了休眠线程的中断: public class SleepInterrupt extends Object implements Runnable{ public void run()

随机推荐