干货-并发编程提高——线程的中断(五)

  1. Jvm在关闭线程之前会检测阻塞在线程对象上的线程。然后执行notfiyAll。这样因join方法阻塞的线程变被会唤醒。
  2. LockSupport.park和LockSupprt.unpark(Thread thread)调用的是native方法。这种形式的阻塞,唤醒对于程序员来说是很友好的。且操作灵活可以指定线程唤醒。LockSupport的核心原理概念是“许可”。如同进京证一样。先搞与晚搞区别不大。在用的时候有就行。当线程调用park方法时,如果有许可的话。那么它可以继续执行。不会被阻塞,但是许可是不可叠加的,只有一次。也是阻塞线程的一种方式。
  3. Interrupt中断方法,并非将线程终止,而是给该线程一个中断信号,线程可自行决定是否终止及其他操作。
  4. 大多数情况下,任务运行完会自动结束。但是有时我们希望提前任务结束,就需要一些非常规手段处理了。如用户取消类似的操作。Java并没有提供任务机制来安全的终止线程。Java只提供了中断,中断是一种协作机制。能使一个线程终止另外一个线程。比如一场马拉松,你突然看A选手不顺眼,你不想让A选手跑完比赛,你为了让它停下来就跑前边儿绊他去。
  5. 中断方法,如果此时要被中断的线程的状态处于(TIME_WAITING,WAITING)状态。当调用中断方法时便会抛出中断异常的错误。InterruptedException。但是当线程处于BLOCKED状态或者RUNNABLE状态时,调用线程的中断方法,也就只能将线程的中断标志为置位true。停止逻辑由程序员自行处理。此场景适用于while循环检测执行的线程是否为中断状态,非中断继续执行。如果未处理,那么中断并无实际意义。
  6. 中断方法原理,首先检查是否有执行中断的权限。然后判断对象是否为空,非空的话,设置中断标识,可以看出当没有进入同步块儿,也就代表线程非TIME_WAITING及WAITING状态。则仅仅设置个标识就出来了。

 

  1. interrupted()方法是一个静态方法,最终会调用具体线程实例的isInterruptrd(boolean ClearInterrupted)方法。传参为true,用于清除中断状态。此方法返回线程是否被中断,且将被判断的线程的状态置为非中断。
  2. IsInterrupted()方法仅仅返回线程的状态是否为中断,并不会对状态标识做任何处理。
  3. 一般方法带 Throw interruptException的就是可以被中断的。对于中断,不要”吞掉”异常。解决不了就往上抛。
  4. Wait/Notify相关 ObjectWaiter对象存在于WaitSet,EntrySet,cxq等集合中。或者正在这些集合中移动
  5. wait方法源码分析:
    1. 首先将当前获得锁的线程,也就是当前在同步块儿中的线程包装成ObjectWaiter对象。并将状态置成TS_WAIT状态,对应jstack的WAITING。
    2. 将ObjectWaiter对象放到WaitSet中,WaitSet实则是一个双向环形链表,将其放到尾部。Wait方法中仅保留有head节点的引用。
    3. 将当前线程挂起,挂起不是阻塞,只有等待锁的线程,才能叫阻塞。依我的理解,所谓挂起就是放到一个特殊的队列
  6. interrupted()方法是一个静态方法,最终会调用具体线程实例的isInterruptrd(boolean ClearInterrupted)方法。传参为true,用于清除中断状态。此方法返回线程是否被中断,且将被判断的线程的状态置为非中断。
  7. IsInterrupted()方法仅仅返回线程的状态是否为中断,并不会对状态标识做任何处理。
  8. 一般方法带 Throw interruptException的就是可以被中断的。对于中断,不要”吞掉”异常。解决不了就往上抛。
  9. Wait/Notify相关 ObjectWaiter对象存在于WaitSet,EntrySet,cxq等集合中。或者正在这些集合中移动
  10. wait方法源码分析:
    1. 首先将当前获得锁的线程,也就是当前在同步块儿中的线程包装成ObjectWaiter对象。并将状态置成TS_WAIT状态,对应jstack的WAITING。
    2. 将ObjectWaiter对象放到WaitSet中,WaitSet实则是一个双向环形链表,将其放到尾部。Wait方法中仅保留有head节点的引用。
    3. 将当前线程挂起,挂起不是阻塞,只有等待锁的线程,才能叫阻塞。依我的理解,所谓挂起就是放到一个特殊的队列
  11. Notify方法分析:
    1. 执行过Wait方法的线程,此时都在WaitSet中,此时从链表中取出第一个元素。
    2. 根据参数:Policy的不同,将这个ObjectWaiter对象放入_EntryList或_cxq队列的起始或者末尾。
  12. 竞争锁失败的线程会被放到monitor对象的_cxq队列首位。
  13. 当线程释放锁时(内置锁):
    1. 依据QMode参数:将ObjectWaiter从_EntryList或_cxq队列中取出唤醒。
    2. 唤醒的元素会继续执行挂起前的操作,通过CAS去竞争锁。
  14. 释放锁时的唤醒逻辑,依据QMode参数。
    1. Case:QMode=2 直接取_cxq中第一位去唤醒,然后跳出剩下的逻辑。
    2. Case:QMode=3 把_cxq队列的首元素放入_EntryList尾部继续执行。
    3. Case:QMode=4 把_cxq队列的首元素放入_EntryList头部,然后继续执行。
    4. Case:QMode=0 默认逻辑兜底逻辑,优先取非空的_EntryList唤醒,否则取_cxq中第一位去唤醒。
    5. 没有1诶
  15. Join方法底层也就是wait方法,所以与可依据上方的逻辑。
  16. 默认情况下也是这样吗?我觉得是不一定,最后慢条斯理的透露出来,然后再一步一步的扯。
  17. Jstack能看到4大状态中,除了New及Terminal
  18. 正是由于CPU只有一个所谓单核,所以CPU处理器分给每个线程的的时间片执行任务,所以叫并发执行。多CPU共同执行,所以叫并行。与GC很像。
  19. 中断后的线程状态即Runable。
  • 12
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值