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仅会补充一份干粮

在这里插入图片描述

  1. 当前线程调用Unsafe.park()方法
  2. 检查_counter,本情况为0,这时,获得_mutex互斥锁
  3. 线程进入_cond条件变量阻塞
  4. 设置_counter=0

在这里插入图片描述

  1. 调用Unsafe.unpark(Thread-0)方法,设置_counter为1
  2. .唤醒_cond条件变量中的Thread-0
  3. Thread-0恢复运行
  4. 设置_counter为0

在这里插入图片描述

  1. 调用Unsafe.unpark(Thread-0)方法,设置_counter为1
  2. 当前线程调用Unsafe.park()方法
  3. 检查_counter,本情况为1,这时线程无需阻塞,继续运行
  4. 设置_counter为0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值