LockSupport学习


常用方法

public static void park(Object blocker); // 暂停当前线程
public static void parkNanos(Object blocker, long nanos); // 暂停当前线程,不过有超时时间的限制
public static void parkUntil(Object blocker, long deadline); // 暂停当前线程,直到某个时间
public static void park(); // 无期限暂停当前线程
public static void parkNanos(long nanos); // 暂停当前线程,不过有超时时间的限制
public static void parkUntil(long deadline); // 暂停当前线程,直到某个时间
public static void unpark(Thread thread); // 恢复当前线程
public static Object getBlocker(Thread t);

unpark(Thread thread)是给资源一个许可,可以继续执行,而这个许可时一对一的,一个unpark只能抵消一个park。但是unpark和park前后顺序无所谓。park()/unpark()底层的原理是“二元信号量”,你可以把它相像成只有一个许可证的Semaphore,只不过这个信号量在重复执行unpark()的时候也不会再增加许可证,最多只有一个许可证。

        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("thread1 start");
                try{
                    Thread.sleep(2000);
                } catch (Exception e){
                    e.printStackTrace();
                }
                System.out.println("thread1 run before park");
                LockSupport.park();
                System.out.println("thread1 run after park");
            }
        });
        thread1.start();
        LockSupport.unpark(thread1);

上例执行结果
在这里插入图片描述
再增加一个park

        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("thread1 start");
                try{
                    Thread.sleep(2000);
                } catch (Exception e){
                    e.printStackTrace();
                }
                System.out.println("thread1 run before park");
                LockSupport.park();
                LockSupport.park();
                System.out.println("thread1 run after park");
            }
        });
        thread1.start();
        LockSupport.unpark(thread1);

卡住
在这里插入图片描述

blocker

作为阻塞线程的标志

public static void park(Object blocker) {
    // 获取当前线程
    Thread t = Thread.currentThread();
    // 设置Blocker
    setBlocker(t, blocker);
    // 获取许可
    UNSAFE.park(false, 0L);
    // 重新可运行后再此设置Blocker
    setBlocker(t, null);
}


LockSupport.park("myblocker");
LockSupport.getBlocker(Thread.currentThread());//返回myblocker

Thread.interrupt()

调用此函数可以唤醒一个park的线程

Object.wait()/notify()

park/unpark相比较于Object.wait()和Object.notify()只能先wait后notify而言更灵活

    static class MyThread extends Thread {
        public void run() {
            synchronized (this) {
                System.out.println("before notify");
                notify();//唤醒wait阻塞线程
                System.out.println("after notify");
            }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        MyThread myThread = new MyThread();
        synchronized (myThread) {
            try {
                myThread.start();
                // 主线程睡眠3s
                Thread.sleep(3000);
                System.out.println("before wait");
                // 阻塞主线程,并释放synchronized中的锁
                //一定要使用当前的锁进行wait,这样等于释放锁了。
                //尝试使用Thread.currentThread().wait()报错current thread is not owner
                myThread.wait();
                //有notify唤醒并获得锁才能继续执行
                System.out.println("after wait");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

执行结果
在这里插入图片描述
请添加图片描述

Object.wait()方法需要在synchronized块中执行;
LockSupport.park()可以在任意地方执行;
Object.wait()方法声明抛出了中断异常,调用者需要捕获或者再抛出;
LockSupport.park()不需要捕获中断异常;
Object.wait()不带超时的,需要另一个线程执行notify()来唤醒,但不一定继续执行后续内容; LockSupport.park()不带超时的,需要另一个线程执行unpark()来唤醒,一定会继续执行后续内容;

参考
https://pdai.tech/md/java/thread/java-thread-x-lock-LockSupport.html#%E4%BD%BF%E7%94%A8waitnotify%E5%AE%9E%E7%8E%B0%E7%BA%BF%E7%A8%8B%E5%90%8C%E6%AD%A5

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值