首页 > 编程语言 >【Java 并发编程】LockSupport

【Java 并发编程】LockSupport

时间:2023-10-17 10:25:36浏览次数:45  
标签:Java 许可 thread 编程 park LockSupport unpark 线程

目录

简介

java.util.concurrent.locks.LockSupport 是一个工具类,提供了基本的线程阻塞和唤醒功能,它是创建锁和其他同步组件的基础工具,内部是基于 sun.misc.Unsafe 类实现的。

LockSupport 和使用它的线程都会关联一个许可:

  • park 方法表示消耗一个许可,调用 park 方法时,如果许可可用,则 park 方法返回,如果没有许可,则一直阻塞直到许可可用;

  • unpark 方法表示增加一个许可,多次调用并不会积累许可,因为许可数最大值为 1。

方法介绍

  • park(): 阻塞当前线程,直到unpark方法被调用或当前线程被中断,park方法才会返回。

  • park(Object blocker): 同park()方法,多了一个阻塞对象blocker参数。

  • parkNanos(long nanos): 同park方法,nanos表示最长阻塞超时时间,超时后park方法将自动返回。

  • parkNanos(Object blocker, long nanos): 同parkNanos(long nanos)方法,多了一个阻塞对象blocker参数。

  • parkUntil(long deadline): 同park()方法,deadline参数表示最长阻塞到某一个时间点,当到达这个时间点,park方法将自动返回。(该时间为从1970年到现在某一个时间点的毫秒数)

  • parkUntil(Object blocker, long deadline): 同parkUntil(long deadline)方法,多了一个阻塞对象blocker参数。

  • unpark(Thread thread): 唤醒处于阻塞状态的线程thread。

阻塞和唤醒示例

示例1

子线程执行 LockSupport.park(),由于没有许可,进入阻塞状态。主线程 3 秒后调用 unpark 方法给子线程增加了一个许可,park 方法返回,子线程被唤醒继续执行。

【示例】:

public class Demo {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            System.out.println("do something start");
            LockSupport.park();
            System.out.println("do something end");
        });

        thread.start();
        Thread.sleep(3000);

        System.out.println("给子线程thread增加一个许可");
        LockSupport.unpark(thread);
    }
}

输出结果:

do something start
给子线程thread增加一个许可
do something end

示例2

先 unpark 增加许可,随后 park 消费许可也是可以的。unpark 会给 thread 增加一个许可,此时调用 park 方法,由于许可是可用的,所以,park 方法直接返回了。

【示例】:

public class Demo {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            System.out.println("do something start");
            System.out.println("子线程thread给自己增加一个许可");
            LockSupport.unpark(Thread.currentThread());
            LockSupport.park();
            System.out.println("do something end");
        });

        thread.start();
    }
}

输出结果:

do something start
子线程thread给自己增加一个许可
do something end

示例3

连续调用 unpark 不会累计许可,许可最大值为1,第一次 park 就已经消耗了许可,所以第二次 park 一直阻塞。

public class Demo {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            System.out.println("do something start");

            LockSupport.unpark(Thread.currentThread());
            System.out.println("unpark 1");
            LockSupport.unpark(Thread.currentThread());
            System.out.println("unpark 2");

            LockSupport.park();
            System.out.println("park 1");
            LockSupport.park();
            System.out.println("park 2");

            System.out.println("do something end");
        });

        thread.start();
    }
}

输出结果:

do something start
unpark 1
unpark 2
park 1

阻塞对象 blocker 的作用

通过前面方法介绍可以看到,park、parkNanos、parkUntil 方法都有对应的带阻塞对象 blocker 参数的重载方法。Thread 类有一个变量为 parkBlocker,对应的就是 LockSupport 的 park 等方法设置进去的阻塞对象。

该参数主要用于问题排查和系统监控,在线程 dump 中会显示该参数的信息,有利于问题定位。

【示例】

分别调用 park() 和 park(Object blocker),然后使用 jstack 查看线程堆栈信息,对比发现后者会多输出一条阻塞对象的信息:

park():

public class Demo {
    public static void main(String[] args) {
        LockSupport.park();
    }
}

image

park(Object blocker):

public class Demo {
    public static void main(String[] args) {
        LockSupport.park(new Demo());
    }
}

image

和显式锁、隐式锁等待唤醒的区别

  • park和unpark方法的调用不需要获取锁。

  • 先调用unpark方法后调用park方法依然可以唤醒。

  • park方法响应中断,线程被中断后park方法直接返回,但是不会抛InterruptedException异常。

  • unpark方法是直接唤醒指定的线程。

参考:

标签:Java,许可,thread,编程,park,LockSupport,unpark,线程
From: https://www.cnblogs.com/larry1024/p/17769054.html

相关文章

  • Javascript报错:Uncaught TypeError: $(...).slide is not a function
    检查网站的时候,发现网页出现一个报错,UncaughtTypeError:$(...).slideisnotafunction同时,平时没有问题的轮播图,也不轮播了。检查并解决步骤如下: 1.顺着错误提示点过去,发现就是slide函数无法运行。查看相关介绍,表示是jq文件进行了重复引用,且版本不同 如下图相关资料描......
  • 编程到底难在哪里?
    大家好,我是陶朱公Boy,一个认真生活,总想超越自己的程序员。前言知乎上有一个提问:编程到底难在哪里?↓↓↓今天,我们就这个话题,一起来做个讨论。首先调研一下,程序员的你,觉得编程难吗?如果觉得难,那到底难在哪里?有哪些地方,是你觉得自己在目前的工作或学习中,自己尚有欠缺的,需要花时......
  • Java IO 与 NIO:高效的输入输出操作探究
    引言输入输出(IO)是任何编程语言中的核心概念,而在Java中,IO操作更是应用程序成功运行的基石。随着计算机系统变得越来越复杂,对IO的要求也日益增加。在本文中,我们将探讨JavaIO和非阻塞IO(NIO)的重要性以及如何在Java中实现高效的输入输出操作。传统IO(阻塞IO)传统IO是大多数开发人员熟......
  • #关于编程小白的初次学习
    关于编程小白的学习之对前后端的理解及选择​据个人理解我把数据库比作一位数学出题者,而后端要做的就是解出这道数学题,并将这个答案交给前端。对于前端,后端给的答案终究还是太过枯燥无味,于是前端的任务就是把这个答案美化,让阅卷老师(用户)能看得更舒服,这样我们的分数才能高,当然这......
  • 这篇记录一下C#和java中的http request的测试
    1.在c#中,测试http的,一般做一个mock的httpContext,然后里面的request和response都使用mock的,这样设置好后,就可以测试controller2.在java中,因为是httpservelet这些,所以实例化测试创建mock的httprequest这些https://www.baeldung.com/java-httpservletrequest-mock@Testvoid......
  • java学习第一天-安装JDK,运行Hello.java
    卸载JDK删除java的安装目录删除JAVA_HOME删除path下关于java的目录cmd下输入java-version安装JDK华为云JDK下载链接,首先下载JDK下载对应版本安装JDK设置安装路径配置环境变量打开环境变量新建系统变量-->JAVA_HOME配置path变量,新建%JAVA_......
  • Java内部类进行回调的场合和范例
    大力:“内部类回调外部类的实现,是咋回事?”卫琴:“回调实质上是指一个外部类尽管实际上实现了某种功能,但是没有直接提供相应的接口,客户类可以通过这个外部类的内部类的接口来获得这种功能。而这个内部类本身并没有提供真正的实现,仅仅调用外部类的实现。可见,回调充分发挥了内部类具有访......
  • Java 开发环境配置
    转载:https://www.w3cschool.cn/java/java-environment-setup.htmlwindow系统安装java下载JDK 配置环境变量1.右击“我的电脑”→“属性”→“高级系统设置”→“高级”→“环境变量”; 在"系统变量"中设置3项属性,JAVA_HOME,PATH,CLASSPATH(大小写无所谓),若已存在则点击"......
  • 企业微信群机器人发送消息(三)java端如何控制
    1.先在群里添加机器人,然后获取机器人的webhook地址:假设webhook是:https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=693a91f6-7xxx-4bc4-97a0-0ec2sifa5aaa2.有多种方式发送群消息,可以采用curl,也可以采用发送http请求的方式,我这里采用okhttp发送http请求,pom如下:<!--ht......
  • 24-Vue组件化编程-单文件组件
    单文件组件一个文件中只包含有1个组件 组件名的注意事项一个单词组成:1)第一种写法(首字母小写):school2)第二种写法(首字母大写):School,推荐多个单词组成:1)第一种写法(kebab-case命名):my-school2)第二种写法(CamelCase命名):MySchool,推荐 创建一个school.vue文件,通常含有以下三种标签......