本文主要是介绍3.7、Park Unpark,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
基本使用
它们是LockSupport类中的方法
// 暂停当前线程
LockSupport.park();
// 回复某个线程的运行
LockSupport.unpark(暂停线程对象)
先park再unpark
public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {log.debug("start...");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}log.debug("park...");LockSupport.park();log.debug("resume...");}, "t1");t1.start();Thread.sleep(2000);log.debug("unpark...");LockSupport.unpark(t1);}
输出
2022/03/06-16:04:01.033 [t1] c.Test1 - start...
2022/03/06-16:04:02.048 [t1] c.Test1 - park...
2022/03/06-16:04:03.032 [main] c.Test1 - unpark...
2022/03/06-16:04:03.032 [t1] c.Test1 - resume...
先unpark在park
public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {log.debug("start...");try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}log.debug("park...");LockSupport.park();log.debug("resume...");}, "t1");t1.start();Thread.sleep(1000);log.debug("unpark...");LockSupport.unpark(t1);}
输出
2022/03/06-16:07:24.562 [t1] c.Test2 - start...
2022/03/06-16:07:25.569 [main] c.Test2 - unpark...
2022/03/06-16:07:26.571 [t1] c.Test2 - park...
2022/03/06-16:07:26.571 [t1] c.Test2 - resume...
特点
与Object的wait & notify相比
- wait、notify和notifyAll必须配合Object Monitor一起使用,而park,unpark不必
- park & unpark 是以线程为单位来【阻塞】和【唤醒】的,而notify只能随机唤醒一个等待线程,notifyAll是唤醒所有线程,就不那么【精确】
- park & unpark可以先unpark,而wait & notify不能先notify
原理
每个线程都有自己的Parker对象,由三部分组成 _counter
、_cond
、_mutex
打个比喻
- 线程就想一个旅人,Parker就像他随身携带的背包,条件变量就好比背包中的帐篷,_counter就好比背包中的干粮(0为耗尽,1为充足)
- 调用park就要看需不需要停下来休息
- 如果干粮耗尽,那么钻进帐篷休息
- 如果干粮充足,那么不需要停留,继续前进
- 调用unpark,就好比令干粮充足
如果这时线程还在帐篷,就唤醒让他继续前进
如果这时线程还在运行,那么下次他调用park时,仅消耗干粮,不需要停留,继续前行
- 因为背包空间有限,多次调用unpark仅会补充一份干粮
- 当前线程调用Unsafe.park()方法
- 检查_counter,本情况为0,这时,获得_mutex互斥锁
- 线程进入_cond条件变量阻塞
- 设置_counter=0
- 调用Unsafe.unpark(Thread-0)方法,设置_counter为1
- .唤醒_cond条件变量中的Thread-0
- Thread-0恢复运行
- 设置_counter为0
- 调用Unsafe.unpark(Thread-0)方法,设置_counter为1
- 当前线程调用Unsafe.park()方法
- 检查_counter,本情况为1,这时线程无需阻塞,继续运行
- 设置_counter为0
这篇关于3.7、Park Unpark的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!