多线程编程-interrupt()

  今天在看板桥人的Java实用系统指南一书的过程中,其中提出了一个使用while (!Thread.interrupted())代替while(true)语句,使得线程在执行错误时能够放弃对CPU独霸的方法,由于在项目中对线程的编程比较少,因此就在网上查找了一下interrupt()方法的具体含义和用途,不查不知道,一查吓一跳,看来自己真应该好好补补了,在此转载一篇个人认为讲解得比较好的文章,希望能帮助到大家

转自:http://blog.youkuaiyun.com/axman/archive/2005/12/26/562249.aspx

 

[线程的中断]

不客气地说,至少有一半人认为,线程的"中断"就是让线程停止.()
如果你也这么认为,那你对多线程编程还没有入门.

在java中,线程的中断(interrupt)只是改变了线程的中断状态,至于这个中断状态改变后带来的结果,那是无法确定的,有时它更是让停止中的线程继续执行的唯一手段.不但不是让线程停止运行,反而是继续执行线程的手段.


对于执行一般逻辑的线程,如果调用调用它的interrupt()方法,那么对这个线程没有任何影响,比如线程a正在执行:
    while(条件) x ++;
这样的语句,如果其它线程调用a.interrupt();那么并不会影响a对象上运行的线程,如果在其它线程里测试a的中断状态它已经改变,但并不会停止这个线程的运行.

在一个线程对象上调用interrupt()方法,真正有影响的是wait,join,sleep方法,当然这三个方法包括它们的重载方法.

请注意:[上面这三个方法都会抛出InterruptedException],记住这句话,下面我会重复.
一个线程在调用interrupt()后,自己不会抛出InterruptedException异常,所以你看到interrupt()并没有抛出这个异常,所以我上面说如果线程a正在执行while(条件) x ++;
你调用a.interrupt();后线程会继续正常地执行下去.

但是,如果一个线程被调用了interrupt()后,它的状态是已中断的.这个状态对于正在执行wait,join,sleep的线程,却改变了线程的运行结果.

    一.对于wait中等待notify/notifyAll唤醒的线程,其实这个线程已经"暂停"执行,因为它正在某一对象的休息室中,这时如果它的中断状态被改变,那么它就会抛出异常.这个InterruptedException异常不是线程抛出的,而是wait方法,也就是对象的wait方法内部会不断检查在此对象上休息的线程的状态,如果发现哪个线程的状态被置为已中断,则会抛出InterruptedException,意思就是这个线程不能再等待了,其意义就等同于唤醒它了.

    这里唯一的区别是,被notify/All唤醒的线程会继续执行wait下面的语句,而在wait中被中断的线程则将控制权交给了catch语句.一些正常的逻辑要被放到catch中来运行.
    但有时这是唯一手段,比如一个线程a在某一对象b的wait中等待唤醒,其它线程必须获取到对象b的监视锁才能调用b.notify()[All],否则你就无法唤醒线程a,但在任何线程中可以无条件地调用a.interrupt();来达到这个目的.只是唤醒后的逻辑你要放在catch中,当然同notify/All一样,继续执行a线程的条件还是要等拿到b对象的监视锁.

    二.对于sleep中的线程,如果你调用了Thread.sleep(一年);现在你后悔了,想让它早些醒过来,调用interrupt()方法就是唯一手段,只有改变它的中断状态,让它从sleep中将控制权转到处理异常的catch语句中,然后再由catch中的处理转换到正常的逻辑.同样,地于join中的线程你也可以这样处理.
   

    对于一般介绍多线程模式的书上,他们会这样来介绍:当一个线程被中断后,在进入wait,sleep,join方法时会抛出异常.
    是的,这一点也没有错,但是这有什么意义呢?如果你知道那个线程的状态已经处于中断状态,为什么还要让它进入这三个方法呢?当然有时是必须这么做的,但大多数时候没有这么做的理由,所以我上面主要介绍了在已经调用这三个方法的线程上调用interrupt()方法让它中这本个方法的"暂停"状态中恢复过来.这个恢复过来就可以包含两个目的:
    一.[可以使线程继续执行],那就是在catch语句中招待醒来后的逻辑,或由catch语句
转回正常的逻辑.总之它是从wait,sleep,join的暂停状态活过来了.
    二.[可以直接停止线程的运行],当然在catch中什么也不处理,或return,那么就完成
了当前线程的使命,可以使在上面"暂停"的状态中立即真正的"停止".

 

 

中断线程

有了上面的[线程的中断],我们就好进行如何[中断线程]了.这绝对不是玩一个文字游戏.
是因为"线程的中断"并不能保证"中断线程",所以我要特别地分为两节来说明.

这里说的"中断线程"意思是"停止线程",而为什么不用"停止线程"这个说法呢?

因为线程有一个明确的stop方法,但它是反对使用的,所以请大家记住,在java中以后不要提停止线程这个说法,忘记它!

 但是,作为介绍线程知识的我,我仍然要告诉你为什么不用"停止线程"的理由.

[停止线程]
 当在一个线程对象上调用stop()方法时,这个线程对象所运行的线程就会立即停止,并抛出特殊的ThreadDeath()异常.这里的"立即"因为太"立即"了,就象一个正在摆弄自己的玩具的孩子,听到大人说快去睡觉去,就放着满地的玩具立即睡觉去了.这样的孩子是不乖的.

假如一个线程正在执行:

synchronized void {
   x = 3;
   y = 4;
}

 
由于方法是同步的,多个线程访问时总能保证x,y被同时赋值,而如果一个线程正在执行到x = 3;时,被调用了 stop()方法,即使在同步块中,它也干脆地stop了,这样就产生了不完整的残废数据.而多线程编程中最最基础的条件要保证数据的完整性,所以请忘记线程的stop方法,以后我们再也不要说"停止线程"了.

 如何才能"结束"一个线程?
[中断线程]
 结束一个线程,我们要分析线程的运行情况.也就是线程正在干什么.如果那个孩子什么事也没干,那就让他立即去睡觉.而如果那个孩子正在摆弄他的玩具,我们就要让它把玩具收拾好再睡觉.

 所以一个线程从运行到真正的结束,应该有三个阶段:

 1.正常运行.
 2.处理结束前的工作,也就是准备结束.
 3.结束退出.

 在我的JDBC专栏中我N次提醒在一个SQL逻辑结束后,无论如何要保证关闭Connnection那就是在finally从句中进行.同样,线程在结束前的工作应该在finally中来保证线程退出前一定执行:

 try{
  正在逻辑
 }catch(){}
 finally{
  清理工作
 }

那么如何让一个线程结束呢?既然不能调用stop,可用的只的interrupt()方法.但interrupt()方法只是改变了线程的运行状态,如何让它退出运行?

 对于一般逻辑,只要线程状态为已经中断,我们就可以让它退出,所以这样的语句可以保证线程在中断后就能结束运行:

 while(!isInterrupted()){
  正常逻辑
 }
 这样如果这个线程被调用interrupt()方法,isInterrupted()为true,就会退出运行.但是如果线程正在执行wait,sleep,join方法,你调用interrupt()方法,这个逻辑就不完全了.

 如果一个有经验的程序员来处理线程的运行的结束:

 public void run(){
   try{
       while(!isInterrupted()){
          正常工作
       }
   }
   catch(Exception e){
      return;
   }
   finally{
      清理工作
   }
 
 }
我们看到,如果线程执行一般逻辑在调用innterrupt后.isInterrupted()为true,退出循环后执行清理工作后结束,即使线程正在wait,sleep,join,也会抛出异常执行清理工作后退出.
这看起来非常好,线程完全按最我们设定的思路在工作.但是,并不是每个程序员都有这种认识,如果他聪明的自己处理异常会如何?事实上很多或大多数程序员会这样处理:

 public void run(){
 
  while(!isInterrupted()){
   try{
    正常工作
   }catch(Exception e){
    //nothing
   }
   finally{
  
   }
  }
 }

 想一想,如果一个正在sleep的线程,在调用interrupt后,会如何?
 wait方法检查到isInterrupted()为true,抛出异常,而你又没有处理.而一个抛出了InterruptedException的线程的状态马上就会被置为非中断状态,如果catch语句没有处理异常,则下一次循环中isInterrupted()为false,线程会继续执行,可能你N次抛出异常,也无法让线程停止.

 那么如何能确保线程真正停止?
 在线程同步的时候我们有一个叫"二次惰性检测"(double check),能在提高效率的基础上又确保线程真正中同步控制中.
 那么我把线程正确退出的方法称为"双重安全退出",即不以isInterrupted()为循环条件.而以一个标记作为循环条件:

class MyThread extend Thread{
 private boolean isInterrupted = false;//这一句以后要修改

 public void interrupt(){
  isInterrupted = true;
  super.interrupt();
 }
 public void run(){
 
  while(!isInterrupted){
   try{
    正常工作
   }catch(Exception e){
    //nothing
   }
   finally{
  
   }
  }
 }
}

试试这段程序,可以正确工作吗?
对于这段程序仍然还有很多可说的地方,先到这里吧.

 

掌握多线程编程:线程中断与下载管理 本文探讨了多线程应用中的一个重要方面:如何优雅地中断和管理下载线程。介绍了Thread类中的interrupt()方法,并通过实际案例展示了如何在下载操作中应用此方法来安全地中断线程,同时讨论了已弃用的线程控制方法,以及如何用更安全的实践来替代它们。此外,还介绍了一个能够同时管理多个下载任务的DownloadFiles类。 阅读详情

相关推荐

BMS短路测试避坑指南:从炸管到稳定,我是如何搞定MOS管和TVS的

本文详细记录了BMS短路测试中MOS管和TVS的优化过程,从驱动电阻调整、PCB寄生参数控制到TVS选配策略,提供了一套实用的调试方法论。通过实战案例解析,帮助工程师避免常见陷阱,实现稳定可靠的短路测试性能。

weixin_30652897的博客 140

《多线程编程》学习之三:停止线程 interrupt()、isInterrupted()、 Thread.interrupted()

1、停止线程 1.1 停止不了的线程       interrupt()方法不会终止一个正在运行的线程,它只是给线程打上一个标志。         可见,调用interrupt()方法并没有停止线程。 1.2  判断线程是否是停止状态 1.2.1   Thread.interrupted():测试当前执行的线程是否已经中断,会清除线程的中断状态。 例子一:

studyhxz的博客 1313

Dify 部署与使用

本文介绍了Dify社区版的快速部署指南,涵盖系统架构、环境配置和初始化流程。Dify采用微服务架构,通过Docker Compose一键部署8个核心容器,包括前端、后端、数据库等组件。部署过程包括克隆代码、配置环境变量和启动服务,首次启动需3-10分钟下载镜像。文章详细讲解了.env文件的配置要点,包括服务地址、数据库连接和向量存储设置,并提供了生产环境安全加固建议。最后通过访问/install页面完成管理员账号初始化,即可开始使用Dify构建AI应用。

海兰 585

Java多线程sleep(),join(),interrupt(),wait(),notify()

关于Java多线程知识可以看看《Thinking in Java 》中的多线程部分和《Java网络编程》中第5章多线程的部分以下是参考>的 1. sleep() & interrupt()     线程A正在使用sleep()暂停着: Thread.sleep(100000);     如果要取消他的等待状态,可以在正在执行的线程里(比如这里是B)调用         a.interrupt();

Potter:I am not for learning and learning, but for study and work 2865

yolo自动化项目实例解析(九) 导航

比如我们经常使用的导航,说白了就是寻找两点之间最近的路径,也就是所谓的寻路,我们需要想办法让程序知道他要去哪里,路径包含(起点、轨迹、路径)

默子昂 1994

【气候极端指数】MATLAB计算各种气候极端指数

简介各类气候极端指数,及其MATLAB计算代码

WW、forever的博客 4916

java 多线程编程中interrupt(),interrupted()和isInterrupted()用法

最近,笔者在学习高洪岩老师的《java多线程编程核心技术》一书时,在1.7停止线程这一小节时,敲击p27的代码时得到的Run3类的运行结果和书上总是不一致。System.out.println("是否停止1? ="+ThreadInterrupt.interrupted());得到的一直是false。并且在请群里的网友和同事运行时也是得到false。但是看网上的博文,大家得到的结果都是true,于...

热爱诗与歌,享受编程每一刻。 519

背靠背VSC直流母线电压控制与同步发电机并网发散问题:原理、分析与解决方案

背靠背VSC直流母线电压控制与同步发电机并网发散问题分析 摘要: 本文研究了背靠背VSC系统在整流侧由理想三相电源切换为同步发电机时出现的直流母线电压振荡和发散问题。通过理论分析发现,锁相环同步失稳、等效阻抗失配和直流母线电容参数失配是导致系统失稳的关键因素。当整流侧接入同步发电机后,系统形成正反馈振荡回路,同时等效电感增大导致电流环响应速度降低,直流侧电容容量不足无法吸收发电机功率波动。文章提出了从跟网型控制到构网型VSG控制的完整升级方案,包含详细的MATLAB/Simulink建模和控制算法实现,并通

huanghm88的专栏 120

java多线程编程核心技术笔记-停止线程interrupt()方法

本文没有太多的语言描述,我认为代码和注释能更好的理解,工作多年接触多线程开发也不少,这里从头看看书加深学习.

无业游民的专栏 310

Carla中如何渲染opendrive车道线和车道标识(全网独家,附代码)

carla是可以单独加载opendrive并渲染路面的,但是无法把车道线渲染出来,这是一个大坑,因为没有车道线就无法给感知输入。楼主已经实现,直接渲染车道线或者带PBR贴图的车道标识。实现起来非常简单,但必须对carla源码以及ue的开发足够了解。在carla源码中有一个很重要的类opendrivegenerator,它是关于opendrive渲染的全部方法,但是你是找不到它实例化的地方的,因为它被定义在蓝图关卡中。网上包括carla官方关于carla源码的分析少之又少,楼主将自己的经验写出来供大家参考。

u013998156的博客 1089

STM32入门教程:无人机控制

我们将会一步一步引导您完成无人机的控制代码,包括无人机的姿态控制、飞行控制和通信控制等。第三步:配置无人机姿态控制 无人机的姿态控制是指控制无人机在空中的倾斜和转向。为了实现姿态控制,我们需要使用加速度计和陀螺仪传感器来获取无人机的姿态信息,并使用PID控制算法来控制无人机的姿态。在这一步骤中,您需要根据您使用的具体传感器和控制算法的要求进行更详细的配置和编码。在通信控制中,您需要考虑到通信的稳定性和可靠性。第五步:通信控制 无人机的通信控制是指与地面站或其他设备进行通信,传输飞行数据和接收飞行指令。

m0_75244442的博客 747

关于对 JUC 的 Interrupt 和 Interrupted 方法的一些理解

在讲到中断方法之前,我们先谈谈什么是线程中断。在Java并发编程中,线程中断是一种协作机制,允许一个线程向另一个线程发出停止正在进行的操作的请求通知。这种通知是通过设置所谓的“中断状态”来实现的。但重要的是,线程中断不是强迫线程停止,而是给线程一个机会来优雅地结束它的执行。这个“机会”实际上是在告诉线程:“你可以继续进行,但有一个请求建议你在下一个合适的时刻停下来。”线程可以检查这个请求(即中断状态),然后决定是否以及何时响应。

weixin_59736343的博客 2204

Android CCodec (四) Output Buffer流程分析

Android 多媒体架构 Codec2 Output Buffer

给大佬递杯卡布奇诺的博客 3264

多线程编程——基础篇 (三)

多线程编程——基础篇 (一) 多线程编程——基础篇 (二)多线程编程——基础篇 (四)  线程对象的几个重要的方法  尽管线程对象的常用方法可以通过API文档来了解,但是有很多方法仅仅从API说明是无法详细了解的。  本来打算用一节的篇幅来把线程方法中一些重要的知识说完,但这样下来估计要很常的篇幅,可能要用好几节才能说把和线程方法相关的一些重要的知识说完。  首先我

leagle 1168

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

java sleep wait join与interrupt的关系

关于Java多线程知识可以看看《Thinking in Java 》中的多线程部分和《Java网络编程》中第5章多线程的部分 以下是参考>的  1. sleep() & interrupt()      线程A正在使用sleep()暂停着: Thread.sleep(100000);      如果要取消他的等待状态,可以在正在执行的线程里(比如这里是B)调用          a.

binboot的专栏 539

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

t.interrupt(), Thread.interrupted(), native isInterrupted()

溺水三千只取一瓢饮 897

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Thread.interrupt():中断阻塞(的)线程,(跳出阻塞)使其抛出InterruptedException

tuhuolong的专栏 989

interrupt(),interrupted()与isInterrupted()

关于标题中的三种方法不再总结,主要是记下一个坑,在看《Java多线程编程核心技术》这本书中遇到的坑。我老老实实的打出文中测试代码运行,却得不到书中的结果。 public class mythread extends Thread{ @Override public void run() { // TODO Auto-generated method stub sup...

qq_33667439的博客 255

“全栈2019”Java多线程第六章:中断线程interrupt()方法详解

难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 “全栈2019”Java多线程第六章:中断线程interrupt()方法详解 下一章 “全栈2019”Java多线程第七章:等待线程死亡join()方法详解 学习小组 加入同步学习小组,共同交流与进步。 方式一:关注头条号Gorhaf,私...

人人都是程序员官方博客 470

Java并发编程高级 难点 多线程中断机制 中断机制 volatile变量 原子类 Thread自带API interrupt()和isInterrupt()

首先一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止。所以,Thread.stop,Thread.suspend, Thread.resume 都已经被废弃了。其次在Java中没有办法立即停止一条线程,然而停止线程却显得尤为重要,如取消一个耗时操作。因此,Java提供了一种用于停止线程的机制--中断。中断只是一种协作机制,Java没有给中断增加任何语法,中断的过程完全需要程序员自己实现。

多多的博客 1002

高并发,高可用,多线程等等问题

需求;根据用户的工资与奖金,按照国家设定的税率,收取费用, 前期的代码 后期的调整 0.线程类常用API大纲 ​ Thread() -----> 无参构造方法 ​ Thread(RUNABLE) ------> RUNABLE参数的构造方法 ​ currentThread() ------> 获取当前线程的方法 ​ isAlive...

汝之秀 500

java多线程中wait()和notify()和notifyAll()及其他常用方法使用

Java线程中sleep()、wait()和notify()和notifyAll()、suspend和resume()、yield()、join()、interrupt()的用法和区别  从操作系统的角度讲,os会维护一个ready queue(就绪的线程队列)。并且在某一时刻cpu只为ready queue中位于队列头部的线程服务。  但是当前正在被服务的线程可能觉得cpu的服务质量不够

每天迈出一小步! 830

多线程编程 基础篇 (三)

基础篇(三) 线程对象的几个重要的方法尽管线程对象的常用方法可以通过API文档来了解,但是有很多方法仅仅从API说明是无法详细了解的.本来打算用一节的篇幅来把线程方法中一些重要的知识说完,但这样下来估计要很常的篇幅,可能要用好几节才能说把和线程方法相关的一些重要的知识说完.首先我们接基础篇(二)来说明start()方法.一个线程对象生成后,如果要产生一个执行的线程,就一定要调用它的start()方...

yesjavame 78
上一篇: EJB的环境
下一篇: JavaScript 匿名函数代码模式
javaRwx
博客等级 码龄20年 0粉丝 22原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值