Java多线程中的wait、notify和park、unpark的使用详解

 更新时间:2023年12月16日 09:36:44   作者:小晨想好好学习  
这篇文章主要介绍了Java多线程中的wait、notify和park、unpark的使用详解,它们都是线程之间进行协作的手段,都属于 Object 对象的方法,必须获得此对象的锁,才能调用这几个方法,需要的朋友可以参考下

一、wait & notify的使用

1、API介绍

  • obj.wait() 让进入 object 监视器的线程到 waitSet 等待
  • obj.wait(n) 让进入 object 监视器的线程到 waitSet 等待,n秒后还没有被唤醒的话,则自动醒来
  • obj.notify() 在 object 上正在 waitSet 等待的线程中挑一个唤醒
  • obj.notifyAll() 让 object 上正在 waitSet 等待的线程全部唤醒

它们都是线程之间进行协作的手段,都属于 Object 对象的方法。

必须获得此对象的锁,才能调用这几个方法 wait() 方法会释放对象的锁,进入 WaitSet 等待区,从而让其他线程就机会获取对象的锁。

无限制等待,直到notify 为止 wait(long n) 有时限的等待, 到 n 毫秒后结束等待,或是被 notify notify 只能随机唤醒一个 WaitSet 中的线程,这时如果有其它线程也在等待,那么就可能唤醒不了正确的线程,称之为【虚假唤醒】

2、demo

@Slf4j(topic = "c.TestCorrectPosture")
public class TestCorrectPostureStep5 {
    static final Object room = new Object();
    static boolean hasCigarette = false;
    static boolean hasTakeout = false;
    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (room) {
                log.debug("有烟没?[{}]", hasCigarette);
                while (!hasCigarette) {
                    log.debug("没烟,先歇会!");
                    try {
                        room.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                log.debug("有烟没?[{}]", hasCigarette);
                if (hasCigarette) {
                    log.debug("可以开始干活了");
                } else {
                    log.debug("没干成活...");
                }
            }
        }, "小南").start();
        new Thread(() -> {
            synchronized (room) {
                Thread thread = Thread.currentThread();
                log.debug("外卖送到没?[{}]", hasTakeout);
                while (!hasTakeout) {
                    log.debug("没外卖,先歇会!");
                    try {
                        room.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                log.debug("外卖送到没?[{}]", hasTakeout);
                if (hasTakeout) {
                    log.debug("可以开始干活了");
                } else {
                    log.debug("没干成活...");
                }
            }
        }, "小女").start();
        sleep(1);
        new Thread(() -> {
            synchronized (room) {
                hasTakeout = true;
                log.debug("外卖到了噢!");
                room.notifyAll();
            }
        }, "送外卖的").start();
    }
}

在这里插入图片描述

2、多线程模式

模式之保护性暂停 模式之生产者消费者

3、wait和notify的原理

在这里插入图片描述

二、Park & Unpark的使用

1、基本使用

它们是 LockSupport 类中的方法

// 暂停当前线程
LockSupport.park(); 
// 恢复某个线程的运行
LockSupport.unpark(暂停线程对象)

先 park 再 unpark

public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            log.debug("start...");
            sleep(1);
            log.debug("park...");
            LockSupport.park();
            log.debug("resume...");
        }, "t1");
        t1.start();
        sleep(4);
        log.debug("unpark...");
        LockSupport.unpark(t1);
    }

在这里插入图片描述

先 unpark 再 park

public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            log.debug("start...");
            sleep(2);
            log.debug("park...");
            LockSupport.park();
            log.debug("resume...");
        }, "t1");
        t1.start();
        sleep(1);
        log.debug("unpark...");
        LockSupport.unpark(t1);
    }

在这里插入图片描述

结论:park和unpark是成对出现,但是是不分先后的

2、特点

与 Object 的 wait & notify 相比

  • wait,notify 和 notifyAll 必须配合 Object Monitor 一起使用,而 park,unpark 不必
  • park & unpark 是以线程为单位来【阻塞】和【唤醒】线程(唤醒的时候可以传一个线程作为参数),而 notify 只能随机唤醒一个等待线程,notifyAll 是唤醒所有等待线程,就不那么【精确】
  • park & unpark 可以先 unpark,而 wait & notify 不能先 notify

到此这篇关于Java多线程中的wait、notify和park、unpark的使用详解的文章就介绍到这了,更多相关Java多线程wait、notify和park内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java简单数据加密方法DES实现过程解析

    Java简单数据加密方法DES实现过程解析

    这篇文章主要介绍了Java简单数据加密方法DES实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • SpringBoot @GroupSequenceProvider注解实现bean多属性联合校验的示例代码

    SpringBoot @GroupSequenceProvider注解实现bean多属性联合校验的示例代码

    这篇文章主要介绍了SpringBoot @GroupSequenceProvider注解实现bean多属性联合校验,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-08-08
  • mybatis主表与明细表一对多的同时插入操作方法

    mybatis主表与明细表一对多的同时插入操作方法

    对主表(采购申请表)和明细表(申请物资表)同时进行插入操作insert,怎么实现呢,下面给大家分享mybatis主表与明细表一对多的同时插入操作方法,感兴趣的朋友一起看看吧
    2023-02-02
  • 一步步带你入门Java中File类

    一步步带你入门Java中File类

    java.io.File类是文件和目录路径名的抽象表示形式,主要用于文件和目录的创建、查找和删除等操作,下面这篇文章主要给大家介绍了关于入门Java中File类的相关资料,需要的朋友可以参考下
    2022-03-03
  • java分析html算法(java网页蜘蛛算法示例)

    java分析html算法(java网页蜘蛛算法示例)

    近来有些朋友在做蜘蛛算法,或者在网页上面做深度的数据挖掘,下面使用示例
    2014-03-03
  • Tomcat处理请求的线程模型详解

    Tomcat处理请求的线程模型详解

    这篇文章主要为大家详细介绍了Tomcat处理请求的线程模型,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • Java基于ReadWriteLock实现锁的应用

    Java基于ReadWriteLock实现锁的应用

    这篇文章主要介绍了Java基于ReadWriteLock实现锁的应用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • 基于springboot i18n国际化后台多种语言设置的方式

    基于springboot i18n国际化后台多种语言设置的方式

    这篇文章主要介绍了基于springboot i18n国际化后台多种语言设置的方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • Java模糊查询方法详解

    Java模糊查询方法详解

    这篇文章主要为大家详细介绍了Java模糊查询方法的实现,实例教你如何用Java做模糊查询结果,感兴趣的小伙伴们可以参考一下
    2016-04-04
  • Spring注解@Scope原理及用法解析

    Spring注解@Scope原理及用法解析

    这篇文章主要介绍了Spring注解@Scope原理及用法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03

最新评论