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开始..

原文地址:https://www.cnblogs.com/oxf5deb3/p/13620424.html