关于java:Java-JUC-LockSupport概述

52次阅读

共计 2238 个字符,预计需要花费 6 分钟才能阅读完成。

LockSupport 工具类

LockSupport 是 rt.jar 包中的一个工具类,它的次要作用就是 挂起 唤醒 线程,并且 该类是创立锁和其它同步类的根底

LockSupport 类和每个应用它的线程都会关联一个 许可证,在默认状况下调用 LockSupport 类的办法是不持有许可证的。LockSupport 是应用 Unsafe 类实现的。

上面介绍一下 LockSupport 中的次要办法。

void park()

如果在调用 park()办法之前曾经取得到关联的许可证,则调用后会立刻返回,否则会被禁止参加线程的调度,也就是被阻塞挂起。

如下代码,最终只会输入“开始”,而后以后线程被挂起,因为在默认状况下调用线程是不持有许可证的。

public static void main(String[] args) throws Exception {System.out.println("开始...");
        LockSupport.park();
        System.out.println("完结...");
}
// 后果:// 开始...

在其它线程调用 unpark(Thread thread)办法并且将以后阻塞线程作为参数时,调用 park()办法阻塞的线程会被返回。当其它线程调用了阻塞线程的 interrupt()办法,设置中断标记或者线程被虚伪唤醒,则阻塞线程也会被返回。

须要留神:

  1. 当调用 park()办法被阻塞的线程被其它线程中断而返回时候,并不会抛出 InterruptedException 异样。
  2. 许可证是一次性的。比方线程 B 间断调用了三次 unpark()办法,当线程 A 调用 park()办法就应用掉这个许可证,如果线程 A 再次调用 park()办法,则进入期待状态。

void unpark(Thread t)

当一个线程调用 unpark()办法时,如果传入的参数 thread 没有持有许可证,则让传入的 thread 持有许可证;如果 thread 之前调用 park()后被挂起,则调用 unpark()时会唤醒该 thread;如果 thread 之前没有调用 park(),则调用 unpark()办法后,再调用 park()办法时会立刻返回。

public static void main(String[] args) throws Exception {System.out.println("开始...");
        LockSupport.unpark(Thread.currentThread());
        LockSupport.park();
        System.out.println("完结...");
}
// 输入后果:// 开始...
// 完结...

看如下代码,加深对 park 和 unpark 的了解。

public static void main(String[] args) throws Exception {Thread t = new Thread(() -> {System.out.println("子线程开始...");
            // 挂起本人
            LockSupport.park();
            System.out.println("子线程完结...");
        });
        t.start();
        Thread.sleep(1000);
        System.out.println("主线程开始调用 unpark");
        LockSupport.unpark(t);
}
// 输入后果:// 子线程开始...
// 主线程开始调用 unpark
// 子线程完结...

该段代码首先创立了子线程 t,子线程启动后调用 park()办法。因为默认状况下子线程没有持有许可证,则挂起本人。

主线程休眠 1 秒后,调用 unpark()并传入子线程 t,这样做就是为了让子线程获取到许可证,之后子线程中阻塞的 park()就会返回。

void parkNanos(long nanos)

和 park()办法相似,如果曾经获取到了许可证则调用该办法后会马上返回。不同的是,如果没有拿到许可证,则调用线程会被挂起 nanos 工夫后主动返回。

另外 park()办法还反对带有 blocker 参数的办法 void park(Object blocker)办法,当线程在没有持有许可证的状况下调用 park()办法而被阻塞挂起时,这个 blocker 对象会被记录到该线程外部。个别用于用于标识阻塞对象,该对象次要用于问题排查和系统监控

void parkNanos(Object blocker,long nanos) 该办法绝对于上个办法,减少了超时工夫。

void parkUntil(Object blocker,long deadline)

public static void parkUntil(Object blocker, long deadline) {Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        UNSAFE.park(true, deadline);
        setBlocker(t, null);
}

参数 deadline 的工夫单位为 ms,这个办法和 parkNanos(Object blocker,long nanos)的区别是,后者是从以后工夫期待 nanos 秒工夫,而前者是指定一个工夫点,比方 2022-01-19 12:00:00。

总结

与 Object 类的 wait/notify 机制相比,park/unpark 有两个长处:

  • 以 thread 为操作对象更合乎阻塞线程的直观定义
  • 操作更精准,能够精确地唤醒某一个线程(notify 随机唤醒一个线程,notifyAll 唤醒所有期待的线程),减少了灵活性

正文完
 0