当前位置: 首页 > news >正文

JUC 之 线程阻塞工具 LockSupport

——LockSupport 与 线程中断

线程中断机制

  • 一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止,所以,Thread.stop,Thread.suspend,Thread.resume 都已经被废弃

  • 在 Java 中没有办法立即停止一条线程,然而停止线程却显得尤为重要,如取消一个耗时操作。因此,Java 提供了一种用于停止线程的协商机制——中断,即中断标识协商机制

  • 中断只是一种协作协商机制,Java 没有给中断增加任何语法,中断的过程完全需要程序员自己实现。若要中断一个线程,你需要手动调用该线程的 interrupt 方法,该方法也仅仅是将线程对象的中断标识设成 true;接着你需要自己写代码不断地检测当前线程的标识位,如果为 true,表示别的线程请求这条线程中断,此时该做什么需要你自己写代码实现

  • 每个线程对象中都有一个中断标识位,用于表示线程是否被中断;该标识位为 true 表示中断,为 false 表示未中断;通过调用线程对象的 interrupt 方法将该线程的标识位设为 true,可以在别的线程中调用,也可以在自己的线程中调用

  • interrupt() :设置线程的中断状态为 true,发起一个协商而不会立刻停止线程

  • interrupted()

    • 返回当前线程的中断状态,测试当前线程是否已被中断
    • 将当前线程的中断状态清零并重新设为 false,清除线程的中断状态
    • 此方法不好理解,如果连续两次调用此方法,则第二次调用将返回 fasle,因为连续调用两次的结果可能不太一样
  • isInterrupted() : 判断当前线程是否已被中断(通过检查中断标志位)

如何停止中断运行中的线程

  • 通过一个 volatile 变量实现:一个线程修改变量值,另一个线程监听,当变量状态值发生变更,跳出线程运行
  • 通过 AtomicBoolean 变量实现
  • 通过 Thread 类自带的中断 api 实例方法实现
    • 具体来说,当对一个线程调用 interrupt() 时
      • 如果线程处于正常活动状态,那么会将该线程的中断标志设置为 true,仅此而已。被设置中断标志的线程继续正常运行,不受影响。所以,interrupt() 并不能真正的中断线程,需要被调用的线程自己进行配合才行
      • 如果线程处于阻塞状态(sleep,wait,join等状态),在别的线程中调用当前线程对象的 interrupt() ,那么线程将立即退出被阻塞状态,并抛出 InterruptedException 异常,中断状态将会被清除(线程无法中断,继续运行,需要在异常出再次中断

LockSupport

  • 是一个线程阻塞工具类,是用来创建锁 和 其他同步类 的基本线程阻塞原语
  • LockSupport 中的 park()unpark(Thread thread) 的作用分别是 阻塞线程 和 解除阻塞线程(唤醒)
  • LockSupport 类使用了一种名为 Permit(许可证) 的概念做到 阻塞和唤醒线程 的功能,每个线程都有一个许可(permit),许可的累加上限是1

线程等待和唤醒

  • 使用 Object 中的 wait 方法让线程等待,使用 Object 中的 notify 方法唤醒线程
    • wait 和 notify 方法必须要在同步块或者方法里面, 且成对出现使用
    • 顺序上先 wait 后 notify,否则无法唤醒
  • 使用 JUC 包中的 Condition 的 await 方法让线程等待,使用 signal 方法唤醒线程
    • Condition 中的线程等待和唤醒方法,需要先获取锁
    • 一定要先 await 后 signal,线程才能被唤醒

以上两个对象使用的限制条件

  • 线程先要获得并持有锁,必须在锁块(synchronized 或 lock)中
  • 必须要先等待后唤醒,线程才能够被唤醒

LockSupport 无限制条件

  • LockSupport 类可以阻塞当前线程以及唤醒指定被阻塞的线程
  • 许可证不会累计,只有一个,不允许多对多

为什么可以突破 wait、notify 的原有调用顺序?

  • 因为 unpark 获得了一个凭证,之后再调用 park 方法,就可以名正言顺的凭证消费,不会阻塞,先发放了凭证后续可以畅通无阻

为什么唤醒两次后阻塞两次,但最终结果还是会阻塞线程?

  • 因为凭证的数量最多为1,连续调用两次 unpark 和调用一次 unpark 效果一致,只会增加一个凭证;而调用两次 park 却需要消费两个凭证,证不够,不能房型
http://www.lryc.cn/news/20235.html

相关文章:

  • 常用数据结构总结-Java版
  • 【基础算法】二分例题(我在哪?)
  • 怕上当?来看这份网络钓鱼和诈骗技术趋势
  • 2023年全国最新保安员精选真题及答案6
  • unity热更新新方案,ILRuntime
  • 【J1】【队列】报数游戏
  • 《程序员的自我修养》阅读笔记
  • 【跟着ChatGPT学深度学习】ChatGPT带我入门深度学习
  • 软工2023个人作业一——阅读和提问
  • 【Redis】线程模型:Redis是单线程还是多线程?
  • FSM(有限状态机)
  • 奇妙的background-clip:text
  • Vmware虚拟机无法联通主机解决方法二
  • Boost资料整理备忘
  • 规则引擎与风控系统01:新问题,新挑战
  • Oracle-00-卸载篇
  • Java线程池使用与原理解析1(线程池优点、使用方法、参数含义及线程池运转机制)
  • windows下编译leveldb(动态库+静态库)
  • 如何用76行代码写一个AI微信机器人......
  • 拿下域控后,我还是对大佬的操作念念不忘
  • 实习-----Mybatis 框架
  • 【Linux】孤儿进程 | 环境变量 | 命令行参数 | 进程优先级
  • Matlab字符串相关操作-拼接、格式化
  • 死磕Spring系列,SpringBoot启动流程
  • 关于条件变量wait操作中锁的作用
  • JUC并发编程与源码分析笔记09-原子类操作之十八罗汉增强
  • 含分布式电源的配电网日前两阶段优化调度模型(Matlab代码实现)
  • FreeRTOS的Delay函数
  • HCIA-HarmonyOS Application Developer——题目集1
  • 高性能 Message ToJavaBean 工具 【easy.server.mapper】