• J.U.C之LockSupport


    一、与wait/notify区别

    ​ wait/notify 为Object中的方法,在调用这两个方法前必须要先获得对象的锁,而locksupport则无需获取对象锁就可以锁定指定线程。

    ​ nodify 只能唤醒任意线程,而locksupport 可以唤醒指定线程,且park不需要捕获中断异常,wait 需要。

    二、怎么用

    ​ 主要是park/unpark, park字面意思停车,形象解释为叫这个线程你站住,你停一下。unpark 就是你继续走。park 和 unpark 就是一个消耗许可和产生许可的过程。底层维护了一个计数器_counter, 多次调用unpark 只会多次将_counter置为1,而不是加1,简单说就是:线程A连续调用两次LockSupport.unpark(B)方法唤醒线程B,然后线程B调用两次LockSupport.park()方法, 线程B依旧会被阻塞。因为两次unpark调用效果跟一次调用一样,只能让线程B的第一次调用park方法不被阻塞,第二次调用依旧会阻塞。每一个线程都会维护着这样一个许可.

    public static void park() {
        UNSAFE.park(false, 0L);
    }
    
    public static void unpark(Thread thread) {
        if (thread != null)
            UNSAFE.unpark(thread);
    }
    
    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);
    
    示例:
    public class LockSupportTest {
    
        public static  class  MyThread extends Thread{
            @Override
            public void run() {
                System.out.println("线程开始等待..");
                LockSupport.park();
                try {
                    TimeUnit.SECONDS.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程结束等待..");
            }
        }
        public static  void main(String[] args){
            Thread _t = new MyThread();
            _t.start();
            System.out.println("开始唤醒线程..");
            LockSupport.unpark(_t);
            System.out.println("唤醒线程结束..");
        }
    }
    

    输出:

    开始唤醒线程..
    线程开始等待..
    唤醒线程结束..
    线程结束等待..


    public class LockSupportTest {
    
        public static  class  MyThread extends Thread{
            @Override
            public void run() {
                System.out.println("线程开始等待..");
                System.out.println("第1个park开始...");
                LockSupport.park();
                System.out.println("第1个park结束...");
                try {
                    TimeUnit.SECONDS.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("第2个park开始..");
                LockSupport.park();
                System.out.println("第2个park结束..");
                System.out.println("线程结束等待..");
            }
        }
        public static  void main(String[] args){
            Thread _t = new MyThread();
            _t.start();
            System.out.println("开始唤醒线程..");
            LockSupport.unpark(_t);
            LockSupport.unpark(_t);
            System.out.println("唤醒线程结束..");
        }
    }
    

    输出: 可以看出第2个park未能获取到锁,一直等待

    开始唤醒线程..
    线程开始等待..
    第1个park开始...
    唤醒线程结束..
    第1个park结束...
    第2个park开始..

  • 相关阅读:
    Swift学习——格式控制符和元组流程控制(二)
    boost::string 例题1
    钱币兑换问题
    我心目中的北京大学:从薛定格到王恩哥
    2.1-Java语言基础(keyword)
    【C语言天天练(十)】结构体
    JVM GC调优一则--增大Eden Space提高性能
    C++的一种业务分发方案(另类的工厂模式)
    Eclipse使用方法和技巧二十六:浅谈快捷键
    linux-shell脚本命令之grep
  • 原文地址:https://www.cnblogs.com/oxf5deb3/p/13620424.html
Copyright © 2020-2023  润新知