当前位置: 首页 > article >正文

JUC中的LockSupport工具类的使用下篇

上篇我们讨论过Object和Condtion来控制线程,但是它们有局限性。现在我们来介绍LockSupport

LockSupport类介绍

LockSupport类可以阻塞当前线程以及唤醒指定被阻塞的线程。主要是通过park()和unpark(thread)方法来实现阻塞和唤醒线程的操作的。

每个线程都有一个许可(permit),permit只有两个值1和0,默认是0。

当调用unpark(thread)方法,就会将thread线程的许可permit设置成1(注意多次调用unpark方法,不会累加,permit值还是1)。

当调用park()方法,如果当前线程的permit是1,那么将permit设置为0,并立即返回。如果当前线程的permit是0,那么当前线程就会阻塞,直到别的线程将当前线程的permit设置为1时,park方法会被唤醒,然后会将permit再次设置为0,并返回。

注意:因为permit默认是0,所以一开始调用park()方法,线程必定会被阻塞。调用unpark(thread)方法后,会自动唤醒thread线程,即park方法立即返回。

LockSupport中常用的方法

  • park():阻塞当前线程,如果调用unpark方法或者当前线程被中断,从能从park()方法中返回
  • park(Object blocker):功能同方法1,入参增加一个Object对象,用来记录导致线程阻塞的阻塞对象,方便进行问题排查
  • parkNanos(long nanos):阻塞当前线程,最长不超过nanos纳秒,增加了超时返回的特性
  • parkNanos(Object blocker, long nanos):功能同方法3,入参增加一个Object对象,用来记录导致线程阻塞的阻塞对象,方便进行问题排查
  • parkUntil(long deadline):阻塞当前线程,直到deadline,deadline是一个绝对时间,表示某个时间的毫秒格式
  • parkUntil(Object blocker, long deadline):功能同方法5,入参增加一个Object对象,用来记录导致线程阻塞的阻塞对象,方便进行问题排查

唤醒线程代码如下:

 public static void testLockSupport() throws InterruptedException {
        Thread t1 = new Thread(() -> {
            System.out.println("start=====================>" + Thread.currentThread().getName());

            LockSupport.park();
            System.out.println("end==========================>" + Thread.currentThread().getName());

        }, "t1");
        t1.start();
        TimeUnit.SECONDS.sleep(5);

        LockSupport.unpark(t1);
        System.out.println("unpark=======================> end");
    }

t1中调用 LockSupport.park();让当前线程t1等待,主线程休眠了5秒之后,调用 LockSupport.unpark(t1);将t1线程唤醒,输出结果中1、3行结果相差5秒左右,说明t1线程等待5秒之后,被唤醒了。

LockSupport.park();无参数,内部直接会让当前线程处于等待中;unpark方法传递了一个线程对象作为参数,表示将对应的线程唤醒。


其实这两个方法没有前后关系的。如下代码

 public static void testLockSupportAfter() throws InterruptedException {
        Thread t1 = new Thread(() -> {

            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("start=====================>" + Thread.currentThread().getName());

            LockSupport.park();
            System.out.println("end==========================>" + Thread.currentThread().getName());

        }, "t1");
        t1.start();
        TimeUnit.SECONDS.sleep(1);
        //先执行unpark方法
        LockSupport.unpark(t1);
        System.out.println("unpark=======================> end");
    }

代码中启动t1线程,t1线程内部休眠了5秒,然后主线程休眠1秒之后,调用了 LockSupport.unpark(t1);唤醒线程t1,此时 LockSupport.park();方法还未执行,说明唤醒方法在等待方法之前执行的;输出结果中2、3行结果时间一样,表示 LockSupport.park();没有阻塞了,是立即返回的。

说明:唤醒方法在等待方法之前执行,线程也能够被唤醒,这点是另外2中方法无法做到的。Object和Condition中的唤醒必须在等待之后调用,线程才能被唤醒。而LockSupport中,唤醒的方法不管是在等待之前还是在等待之后调用,线程都能够被唤醒。

线程等待和唤醒的3种方式做个对比

方式1:Object中的wait、notify、notifyAll方法
方式2:juc中Condition接口提供的await、signal、signalAll方法
方式3:juc中的LockSupport提供的park、unpark方法

http://www.kler.cn/a/429423.html

相关文章:

  • 链家房价数据爬虫和机器学习数据可视化预测
  • An FPGA-based SoC System——RISC-V On PYNQ项目复现
  • [UE4图文系列] 5.字符串转中文乱码问题说明
  • VS Code 的扩展下载安装的最新方式
  • 信号与系统初识---信号的分类
  • 论文阅读:Searching for Fast Demosaicking Algorithms
  • 细说敏捷:敏捷四会之回顾会
  • mysql查询一对多重复数据拼接字符串
  • 【八股】HTTP
  • 数据挖掘之聚类分析
  • 网络安全中大数据和人工智能应用实践
  • Google BERT入门(3)Transformer的自注意力机制的理解(上)
  • 3D 生成重建023-DMV3D用扩散模型做3D生成大模型
  • Spring-AOP(面向切面)
  • 深入理解C#的TCPIP通信机制
  • 深度学习:CPU和GPU算力
  • Python基于OpenCV实现的人脸识别和笑容检测
  • 【Apache Paimon】-- 4 -- Flink 消费 kafka 数据,然后写入 paimon
  • Linux如何安装discuz
  • docker安装Emqx并使用自签名证书开启 SSL/TLS 连接
  • 数据库之连接池Druid
  • ZZCMS2023存在跨站脚本漏洞(CNVD-2024-44822、CVE-2024-44818)
  • sock_poll内核函数
  • No module named ‘_ssl‘ No module named ‘_ctypes‘
  • 如何防范顶级应用程序安全威胁
  • 【大语言模型】LangChain ModelsIO与Models I/O Promopts详解