Java线程核心01-中断线程的理论原理

  • 启停原理:使用interrupt来通知,而不是强制
    • 最好停止线程的方式是使用中断interrupt,但这仅仅是通知到被终止的线程"你该停止运行了",被终止的线程自身拥有决定权(决定中否,以及何时停止),这依赖于请求停止方和被停止方都遵守一种约定好的编码规范
    • 任务和线程的启动很容易。大多数情况下,我们都会让它们运行直到结束,或者让它们自行停止。然而,有时候我们希望提前结束任务或线程,或许是因为用户取消了操作,或者服务需要被快速关闭,或者运行超时,或者出错了
    • 要使任务和线程能安全、快速、可靠地停止下来,并不是一件容易的事
    • Java没有提供任何机制来安全地终止线程。但它提供了中断,这是一种协作机制,能够使一个线程终止另一个线程的当前工作
    • 这种协作方式是必要的,几乎很少希望某个任务、线程或服务立即停止,因为这种立即停止会使共享的数据结构处于不一致的状态
    • 所以当需要停止时,会首先清除当前正在执行的工作,然后再结束。这提供了更好的灵活性,因为任务本身的代码比发出取消请求的代码更清楚如何正确执行清除工作
    • 使命周期结束(End-of-Lifecycle)的问题会使任务、服务以及程序的设计和实现等过程变得复杂,而这个在程序设计中非常重要的要素却经常被忽略
    • 一个行为良好的软件与勉强运行的软件之间最主要区别是,行为良好的软件能很完善地处理失败、关闭和取消等过程
  • 停止的情况
    • 线程代码执行完毕
    • 线程内代码抛出异常
    • 线程被阻塞
      • 当线程内部使用代码TimeUnit.SECONDS.sleep(1);进入休眠后,这时如果外部有使用thread.interrupt();来中断时,休眠代码会抛出异常
        • InterruptedException: sleep interrupted
        • 需要注意的是,一旦睡眠被中断会抛出异常,同时会消除线程内的interrupt的标记位,也就是说无法再使用!Thread.cuurentThread.isInterrupted()来判断线程是否被中断
          • 解决这种中断标记位被清除的问题,可以使用传递中断、恢复中断和不屏蔽异常
            • 传递中断:
              • 在方法签名中抛出异常,这样会在run方法中被强制要求对异常进行处理
              • 不要在方法内部try...catch异常,这样会导致异常不能向上传递给run方法,即便方法内部出现异常,也不会被调用者来接收并终止,因为处理异常就会重置中断标记位
              • run方法不允许在签名中抛出异常,必须要在其内部处理
            • 恢复中断:try...catchcatch部分加入代码:Thread.currentThread().interrupted()来恢复被try...catch语句中清除的中断标志,这样就可以在run方法中来判断是否中断来决定程序运行逻辑
    • 响应中断的方法列表
      • Object wait() wait(long) wait(long, int)
      • Thread sleep(long) sleep(long, int)
      • Thread join() join(long) join(long, int)
      • java.util.concurrent.BlockingQueue take() put(E)
      • java.util.concurrent.locks.Lock lockInterruptibly()
      • java.util.concurrent.CountDownLatch await()
      • java.util.concurrent.CyclicBarrier await()
      • java.util.concurrent.Exchanger exchange(V)
      • java.nio.channels.InterruptibleChannel 相关方法
      • java.nio.channels.Selector 相关方法
  • 错误停止线程的方法
    • 使用了已经被弃用的方法:stop() suspend() resume()
      • stop()会释放所有的监视器,但会以一种破坏原子性操作的方式停止线程运行
      • suspend()会挂起线程,但不会释放锁,如果不会被唤醒,或者唤醒它的线程需要它的锁,就容易导致死锁
    • volatile设置boolean标记位
      • 陷入阻塞状态时volatile无法支持终止线程
相关推荐
此时不提桶,更待何时8 分钟前
01-04-B-垃圾回收面试与生产事故实战
java·jvm·面试
伞伞悦读15 分钟前
【第36期】Python 目录与路径详解:pathlib、文件遍历、创建、复制、移动和删除风险
开发语言·python
鹿角片ljp2 小时前
KV Cache 解析
java·算法
captain3762 小时前
网络原理(9)-数据链路层
java·网络协议·java-ee
惊讶的猫3 小时前
意图识别置信度和检索重排的分数
java
2601_966949653 小时前
只拿到股票代码还不够:量化程序到底还需要哪些标的信息?——从数据建模开始理解股票元数据
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
caoerzhong3 小时前
仓库管理数字化趋势解读:JeeWMS 开源 Java WMS 视角下的五个演进方向
java·开源
m0_734571763 小时前
深入理解5g <十八>传输块tbsize的计算
开发语言·5g
程序员JerrySUN4 小时前
Jetson Edge AI 实战01:Nano、Xavier、Orin 怎么选?Jetson 硬件选型详解【视频讲解】
java·数据库·redis·安全·mybatis