使用 interrupt() 和 interrupted() 判断来终止线程


  1. public class Run {
  2. public static void main(String[] args) {
  3. try {
  4. MyThread thread = new MyThread();
  5. thread.start();
  6. Thread.sleep(2000);
  7. thread.interrupt();//请求中断MyThread线程
  8. } catch (InterruptedException e) {
  9. System.out.println("main catch");
  10. e.printStackTrace();
  11. }
  12. System.out.println("end!");
  13. }
  14. }

main线程睡眠2000ms后,执行第8行中断MyThread线程。

  1. public class MyThread extends Thread {
  2. @Override
  3. public void run() {
  4. super.run();
  5. for (int i = 0; i < 500000; i++) {
  6. if (this.interrupted()) {
  7. System.out.println("should be stopped and exit");
  8. break;
  9. }
  10. System.out.println("i=" + (i + 1));
  11. }
  12. System.out.println("this line is also executed. thread does not stopped");//尽管线程被中断,但并没有结束运行。这行代码还是会被执行
  13. }
  14. }

当MyThread获得CPU执行时,第6行的 if 测试中,检测到中断标识被设置。即MyThread线程检测到了main线程想要中断它的 请求。

大多数情况下,MyThread检测到了中断请求,对该中断的响应是:退出执行(或者说是结束执行)。

但是,上面第5至8行for循环,是执行break语句跳出for循环。但是,线程并没有结束,它只是跳出了for循环而已,它还会继续执行第12行的代码....

因此,我们的问题是,当收到了中断请求后,如何结束该线程呢?

一种可行的方法是使用 return 语句 而不是 break语句。。。。。哈哈。。。

不过使用return 没有抛异常那么好,不能将事件传播

优雅的解决

抛异常方法 抛出InterruptedException异常

  1. public class MyThread extends Thread {
  2. @Override
  3. public void run() {
  4. super.run();
  5. try{
  6. for (int i = 0; i < 500000; i++) {
  7. if (this.interrupted()) {
  8. System.out.println("should be stopped and exit");
  9. throw new InterruptedException();
  10. }
  11. System.out.println("i=" + (i + 1));
  12. }
  13. System.out.println("this line cannot be executed. cause thread throws exception");//这行语句不会被执行!!!
  14. }catch(InterruptedException e){
  15. System.out.println("catch interrupted exception");
  16. e.printStackTrace();
  17. }
  18. }
  19. }

当MyThread线程检测到中断标识为true后,在第9行抛出InterruptedException异常。这样,该线程就不能再执行其他的正常语句了(如,第13行语句不会执行)。


因此,上面就是一个采用抛出异常的方式来结束线程的示例。尽管该示例的实用性不大。原因是我们 生吞了中断。

在第14行,我们直接catch了异常,然后打印输出了一下而已,调用栈中的更高层的代码是无法获得关于该异常的信息的。

第16行的e.printStackTrace()作用就相当于

在这里是生吞了异常  由于
this.interrupted()在第一次调用后清楚中断状态为false(注意这里是调用

this.interrupted()这个方法会清楚中断状态,而不是抛出异常会清除中断状态,而isInterrupted()这个不会清除中断状态,这两种区别在

1.仅仅记录 InterruptedException 也不是明智的做法,因为等到人来读取日志的时候,再来对它作出处理就为时已晚了。

有时候抛出 InterruptedException 并不合适,例如当由 Runnable 定义的任务调用一个可中断的方法时,就是如此。在这种情况下,不能重新抛出 InterruptedException,但是您也不想什么都不做。当一个阻塞方法检测到中断并抛出 InterruptedException 时,它清除中断状态。如果捕捉到 InterruptedException 但是不能重新抛出它,那么应该保留中断发生的证据,以便调用栈中更高层的代码能知道中断,并对中断作出响应。该任务可以通过调用 interrupt() 以 “重新中断” 当前线程来完成
2.因为,run方法是实现的Runnable接口中的方法。不能像下面这样定义,也即上面所说的:“不能重新抛出InterruptedException”。
        @Override
public void run() throws InterruptedException{//这是错误的
//do something...

代码改良

  1. public class MyThread extends Thread {
  2. @Override
  3. public void run() {
  4. super.run();
  5. try{
  6. for (int i = 0; i < 500000; i++) {
  7. if (this.interrupted()) {
  8. System.out.println("should be stopped and exit");
  9. throw new InterruptedException();
  10. }
  11. System.out.println("i=" + (i + 1));
  12. }
  13. System.out.println("this line cannot be executed. cause thread throws exception");
  14. }catch(InterruptedException e){
  15. /**这样处理不好
  16. * System.out.println("catch interrupted exception");
  17. * e.printStackTrace();
  18. */
  19. Thread.currentThread().interrupt();//这样处理比较好
  20. }
  21. }
  22. }

这样,就由 生吞异常 变成了 将 异常事件 进一步扩散了。 保留了中断的证据

ps 
对于可取消的阻塞状态中的线程, 比如等待在这些函数上的线程, Thread.sleep(), Object.wait(), Thread.join(), 这个线程收到中断信号interrupt()后, 会抛出InterruptedException。就不需要手动抛异常法了,只需要在捕获异常块再次标记中断即可



java 多线程6: 中断机制 优雅的终止java线程的更多相关文章

  1. Java 多线程基础(十)interrupt()和线程终止方式

    Java 多线程基础(十)interrupt()和线程终止方式 一.interrupt() 介绍 interrupt() 定义在 Thread 类中,作用是中断本线程. 本线程中断自己是被允许的:其它 ...

  2. Java多线程干货系列—(一)Java多线程基础

    前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们来说极其重要,下面跟我一起开启本次的学习之旅吧. 正文 线程与进程 1 线程:进程中负责程序执行的 ...

  3. [转]Java多线程干货系列—(一)Java多线程基础

    Java多线程干货系列—(一)Java多线程基础 字数7618 阅读1875 评论21 喜欢86 前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们 ...

  4. Java多线程编程核心技术-第1章-Java多线程技能-读书笔记

    第 1 章 Java 多线程技能 本章主要内容 线程的启动 如何使线程暂停 如何使线程停止 线程的优先级 线程安全相关的问题 1.1 进程和多线程的概念及线程的优点 进程是操作系统结构的基础:是一次程 ...

  5. “全栈2019”Java多线程第二十二章:饥饿线程(Starvation)详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  6. “全栈2019”Java多线程第十二章:后台线程setDaemon()方法详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

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

    一,介绍 本文记录JAVA多线程中的中断机制的一些知识点.主要是stop方法.interrupted()与isInterrupted()方法的区别,并从源代码的实现上进行简单分析. JAVA中有3种方 ...

  8. JAVA多线程之中断机制(如何处理中断?)

    一,介绍 这篇文章主要记录使用 interrupt() 方法中断线程,以及如何对InterruptedException进行处理.感觉对InterruptedException异常进行处理是一件谨慎且 ...

  9. Java多线程总结(二)锁、线程池

    掌握Java中的多线程,必须掌握Java中的各种锁,以及了解Java中线程池的运用.关于Java多线程基础总结可以参考我的这篇博文Java多线程总结(一)多线程基础 转载请注明出处——http://w ...

随机推荐

  1. 〖Windows〗Linux的Qt程序源码转换至Windows平台运行,编码的解决

    在中国大陆,Windows默认的编码是gb2312,而Linux是UTF8: 多数情况下,把Linux上的程序转换至Windows上运行需要进行编码转换才能正常显示: 而其实大可以不必的,同样,文件使 ...

  2. 〖Linux〗录像桌面视频同时录音

    1. 安装依赖的包 sudo apt-get install -y ffmpeg oss-compat alsa-oss 2. 录制桌面视频并录音 aoss ffmpeg -f oss -i /dev ...

  3. 〖Android〗/system/etc/audio_policy.conf

    原文件注释说明: # audio hardware module section: contains descriptors for all audio hw modules present on t ...

  4. 架构-LAMP特级学习(网站加速解决方案)

    1.Squid代理缓存技术 2.页面静态化缓存技术 3.Memcache.Redis等缓存服务器 4.Sphinx搜索加速

  5. [转载]meclipse中project facet问题

    原文地址:meclipse中project facet问题作者:丫头_樱桃 一般出现在从别处import的项目上,只有项目文件夹上有红叉,其他地方都正常,现总结个人的几个解决方案: 有几种可能: 1, ...

  6. delphi實現按键精靈的功能

    unit kbKernel; interfaceuses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Fo ...

  7. Java JDBC数据库编程

    课程  Java面向对象程序设计 一.实验目的 掌握数据库编程技术 二.实验环境 1.微型计算机一台 2.WINDOWS操作系统,Java SDK,Eclipse开发环境,Microsoft SQL  ...

  8. 【LeetCode】71. Simplify Path

    Simplify Path Given an absolute path for a file (Unix-style), simplify it. For example,path = " ...

  9. Windows下面安装和配置Solr 4.9(一)

       1.Solr下载 下载地址 :http://lucene.apache.org/solr/   2.解压,测试 在example文件夹中找到start.jar文件,用命令提示符运行这个文件:ja ...

  10. pthread到Win32thread

    一.什么是线程. 线程(thread)是为了提高系统内程序的并发(concurrency)执行程度而提出来的概念,它是比进程更小的能够独立运行的基本单位.在引入线程的系统中,线程是处理器调度(sche ...