Java线程中断机制-如何中断线程

版权声明:本文为博主原创文章,欢迎指正或者转载。 https://blog.csdn.net/qq_38663729/article/details/78232648

介绍:

对于线程一共分为五个状态:新建状态,就绪状态,阻塞状态,运行状态,死亡状态,有时候把阻塞状态又分为同步阻塞和等待阻塞。

有时想让主线程启动的一个子线程结束运行,我们就需要让这个子线程中断,不再继续执行。线程是有中断机制的,我们可以对每个线程进行中断标记,注意只是标记,中断与否还是虚拟机自己的事情,虚拟机自己家的事情,我们也就说说,不能实际操作控制他家。java中的Thread类是一个对线程进行操作的类,提供了中断线程的方法interrupt(),在API中是这么定义的(中文的翻译可能不准确)。

在Thread中其实还有一个stop()方法也是中断线程的方法,但是这个方法太粗鲁了,人家好好的线程正在运行,只要调用了stop()方法,线程就会中断,不管是在进行什么操作。这个方法已经被废弃,他的执行会带来一些不可确定的状况。

线程可以调用中断自己的方法interrupt()方法,但是中断也是有条件的,在线程调用interrupt()方法的时候虚拟机会在此线程上标记一个标志(这个中断标志只是一个布尔类型的变量),代表这个线程可能被中断,在后面的中断操作也是根据这个中断标志执行的。可以说interrupt()方法是一种友好的方法,总是和虚拟机商量着来。如果一个线程处于了阻塞状态(如线程调用了sleep()、join()、wait()、以及可中断的通道上的 I/O 操作方法后可进入阻塞状态),则在线程在检查中断标示时如果发现中断标示为true,则会在这些阻塞方法(sleep()、join()、wait()及可中断的通道上的 I/O 操作方法)调用处抛出InterruptedException异常,并且在抛出异常后立即将线程的中断标示位清除,即重新设置为false。抛出异常是为了线程从阻塞状态醒过来,并在结束线程前让程序员有足够的时间来处理中断请求。

线程的一些状态都可能影响到这个中断标记从而结束中断。下面这个例子验证中断标志被除掉的说法

package demo_thread;

public class Interrupt {

 public static void main(String[] args) {

   A a = new A();

   Thread t1 = new Thread(a);

   t1.start();

   t1.interrupt();

   System.out.println("执行睡眠之前1:"+t1.isInterrupted());

   try {

     System.out.println("执行睡眠之前2:"+t1.isInterrupted());

     t1.sleep(1000);//线程进入阻塞状态

   } catch (InterruptedException e) {

     e.printStackTrace();

   }finally {

    System.out.println("执行睡眠之后:"+t1.isInterrupted());

   }

 }

}

class A implements Runnable{

 @Override

 public void run() {

   System.out.println(Thread.currentThread());

 }

}

在main方法中创建一个线程,线程中重写的run()方法输出线程号,只是一个显示分隔,具体看在执行让线程阻塞方法之前和之后线程的中断标记。isInterrupted()方法是判断线程是否执行中断的方法,就是判断中断标记是否存在的方法。

输出:

执行睡眠之前1:true
执行睡眠之前2:true
Thread[Thread-0,5,main]
执行睡眠之后:false

可以看到只要执行了sleep()方法,线程的中断标记就会被清除。分别调用执行了join()、wait()方法,可以看到他们的共同点都是需要捕获一个InterruptedException,在调用join()方法的时候得到了和sleep()方法一样的输出结果,但是在调用wait()方法的时候,虽然在后面调用notify()方法,但是是否获得执行权限还是无法预料的。

中断一个线程只是为了引起该线程的注意,被中断线程可以决定如何应对中断,中断或者不中断。某些线程非常重要,以至于它们应该不理会中断,而是在处理完抛出的异常之后继续执行,但是更普遍的情况是,一个线程将把中断看作一个终止请求。

两个很像的方法的区别:

interrupted():测试当前线程是否中断。 该方法可以清除线程的中断状态 。换句话说,如果这个方法被连续调用两次,那么第二个调用将返回false(除非当前线程再次中断,在第一个调用已经清除其中断状态之后,在第二个调用之前已经检查过)。

isInterrupted():测试这个线程是否被中断。线程的中断状态不受此方法的影响。

如何中断线程:

接下来看请求中断之后发生的事情:在网上看到一个例子

package demo_thread;

 public class Interrupt {

   public static void main(String[] args) {

     try {

      MyThread thread = new MyThread();

      thread.start();

      Thread.sleep(2000);

      thread.interrupt();//请求中断MyThread线程

     } catch (Exception e) {

  System.out.println("main catch");

e.printStackTrace();

}

System.out.println("end!");

}

}

class MyThread extends Thread {

 @Override

 public void run() {

   super.run();

   for (int i = 0; i < 500000; i++) {

     if (this.interrupted()) {

       System.out.println("should be stopped and exit");

       break;

     }

    System.out.println("i=" + (i + 1));

   }

  //尽管线程被中断,但并没有结束运行。这行代码还是会被执行

  System.out.println("this line is also executed. thread does not stopped");

  }

}
在文章的开头处已经说了,线程执行中断方法,只是给线程一个中断标记,是否中断是他自己的事

其中一次的输出:

……
i=75722
end!
should be stopped and exit
this line is also executed. thread does not stopped

由于线程执行了sleep()方法,进入阻塞状态,所以在从阻塞状态从新回到运行状态的时候,发现自己已经有了中断标记,执行if中的语句,线程的睡眠和执行总是和计算机内部有关系,所以每次输出的结束数字总是不一样的。

通过输出结果我们发现一个很重要的问题,我们要的是线程的中断,也就是关于线程的方法需要停止执行,但是在循环外面的输出语句也执行了,这个中断只是中断了循环的执行。

那么我们应该怎么中断线程呢?利用线程中断异常就是一个很好的办法,既然是异常,通常异常可以中断线程的运行,使程序挂掉,我们自己抛出一个异常让线程中断

class MyThread extends Thread {

      @Override

      public void run() {

       super.run();

       try {

         for (int i = 0; i < 500000; i++) {

           if (this.interrupted()) {

             System.out.println("should be stopped and exit");

             throw new InterruptedException();

            }

          System.out.println("i=" + (i + 1));

         }

    System.out.println("this line cannot be executed. cause thread throws exception");//这行语句不会被执行!!!

       } catch (InterruptedException e) {

          System.out.println("catch interrupted exception");

          e.printStackTrace();

     }

  }

}
输出:

……
i=131892
should be stopped and exit
end!

但是通过抛出异常也带来了问题,我们不能通过抛出异常来处理问题,还需要在捕获异常的代码中加上处理的语句,例如保存用户的操作等等,让这次中断看起来是很正常的中断。
我们还可以通过让程序主动抛出异常,在线程阻塞的时候,执行中断操作,抛出异常,在循环中循环打印当前时间,

package demo_thread;

import java.text.SimpleDateFormat;

import java.util.Date;

public class SleepInterruptTest {

 public static void main(String[] args) {

    SleepThread t1 = new SleepThread();

    t1.start();

    try {

      Thread.sleep(5000);

    } catch (InterruptedException e) {

      e.printStackTrace();

    }

   t1.interrupt();//主动打断线程,使SleepThread线程抛出异常

  }

}

class SleepThread extends Thread{

    public void run(){

      while(true){

       try{

         SimpleDateFormat sim = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");

         System.out.println(sim.format(new Date()));

         sleep(1000);

        }

       catch(InterruptedException e){

       System.out.println("线程中断");

       return;

    }

   }

   }

}

Java线程中断机制-如何中断线程相关推荐

  1. java中断线程_Java线程中断机制-如何中断线程

    介绍: 对于线程一共分为五个状态:新建状态,就绪状态,阻塞状态,运行状态,死亡状态,有时候把阻塞状态又分为同步阻塞和等待阻塞. 有时想让主线程启动的一个子线程结束运行,我们就需要让这个子线程中断,不再 ...

  2. Java 线程实例二(终止线程、生产者/消费者问题、获取线程状态、获取所有线程、查看线程优先级、中断线程)

    终止线程 Java中原来在Thread中提供了stop()方法来终止线程,但这个方法是不安全的,所以一般不建议使用. 本文向大家介绍使用interrupt方法中断线程. 使用interrupt方法来终 ...

  3. java终端线程_java多线程-中断线程

    大纲: java线程的中断原则 中断相关方法 中断实例 一.java线程中断原则 java中断是一种协作机制,每一个线程的中断都由线程自己处理,其他线程只是给要中断的线程一个中断标志. 二.相关方法 ...

  4. java 线程 通过interrupted_分析Java线程中断机制stop和interrupted的用法

    1.引言当我们点击某个杀毒软件的取消按钮来停止查杀病毒时,当我们在控制台敲入quit命令以结束某个后台服务时--都需要通过一个线程去取消另一个线程正在执行的任务.Java没有提供一种安全直接的方法来停 ...

  5. java线程池中断处理_Java线程中断机制

    1. 引言 对Java中断没有一个全面的了解,可能会误以为被中断的线程将立马退出运行,但事实并非如此.中断机制是如何工作的?捕获或检测到中断后,是抛出InterruptedException还是重设中 ...

  6. java获取其他类的线程,使用Java实现面向对象编程——第七章 多线程

    1.进程:是指运行中的应用程序,每个进程都有自己独立的地址空间(内存空间): Eg:用户点击桌面的IE浏览器,就启动了一个进程,操作系统就会为该进程分配独立的地址空间.当用户再次点击左面的IE浏览器, ...

  7. python线程异常中断_中断线程

    如果线程需要执行一个长时间任务,就可能需要能中断线程.中断线程就是其他线程给该线程发一个信号,该线程收到信号后结束执行run()方法,使得自身线程能立刻结束运行. 我们举个栗子:假设从网络下载一个10 ...

  8. Linux中断子系统---中断申请request_irq()与中断线程化request_threaded_irq()

    一.申请中断request_irq() Linux中使用中断需要先进行申请,申请中断的API函数如下: int request_irq(unsigned int irq,irq_handler_t h ...

  9. 中断优先级和中断线程优先级

    中断是一种当今很重要的硬件与cpu通信的方式,主板上集成很多硬件,那么就可以认为会有很多中断,但是cpu的数目往往要少得多,那么肯定会有多个硬件中断竞争一个cpu的情况,任何系统(包括自然界)都不能乱 ...

最新文章

  1. linux运维防火墙考题,Linux运维工程师:30道面试题整理 | 张戈博客
  2. HDFS的副本存放策略(机架感知策略)
  3. IDEA使用指南常用快捷键
  4. 操作系统原理之内存管理(第四章第一部分)
  5. 使用Testcontainers和PostgreSQL,MySQL或MariaDB的Spring Boot测试
  6. 400错误是什么原因_499错误是什么?499错误的原因及解决方法
  7. javascript-封闭函数的定义与使用
  8. 【…感激2008,部署我的2009…】
  9. Exchange服务器系统蓝屏及脱域后解决办法
  10. mysql条件变量单引号_mysql语法
  11. BP神经网络——如何进行权值的初始化
  12. 数学建模c语言知识,数学建模方法总结
  13. 啊哈C语言 第四章 【代码】【习题答案】
  14. EXCEL出错 8000401a
  15. ShardingSphere——水平分表与数据迁移
  16. java全栈工程师培训,分享面经
  17. netware php_Apache MPM netware
  18. 【C++】有趣的数字
  19. Kinect 开发 —— 深度信息(二)
  20. 建立自己的数据集 并用Tensorflow object detection API进行训练

热门文章

  1. 计算机设计大赛国奖作品_4. 界面设计
  2. php请求api获取返回值,我用curl请求接口获取返回值,但是不成功,大神给看看怎么调取?...
  3. 奥格斯堡大学计算机系,奥格斯堡大学七大科系设置简介
  4. 简述使用计算机对会计工作的影响,简述使用计算机对会计工作的影响。
  5. python的标准类型内建函数_Python随手笔记之标准类型内建函数
  6. vue 限制渲染条数_深入理解Vue 的条件渲染和列表渲染
  7. python段子_Python爬取内涵段子里的段子
  8. 苹果隐藏app_iOS 14的隐藏功能盘点:不知道等于白更新!
  9. html图片怎么设置行高,html行高怎么设置
  10. opencv1-加载、修改、保存图像