iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >Java线程通信中wait-notify通信的方式是什么
  • 860
分享到

Java线程通信中wait-notify通信的方式是什么

2023-06-29 08:06:51 860人浏览 独家记忆
摘要

这篇文章主要介绍“Java线程通信中wait-notify通信的方式是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java线程通信中wait-notify通信的方式是什么”文章能帮助大家解决问

这篇文章主要介绍“Java线程通信中wait-notify通信的方式是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java线程通信中wait-notify通信的方式是什么”文章能帮助大家解决问题。

    1. 线程通信的定义

    线程是操作系统调度的最小单位,有自己的栈空间,可以按照既定的代码逐步执行,但是如果每个线程间都孤立地运行,就会造资源浪费。所以在现实中,如果需要多个线程按照指定的规则共同完成一个任务,那么这些线程之间就需要互相协调,这个过程被称为线程的通信。

    线程的通信可以被定义为:当多个线程共同操作共享的资源时,线程间通过某种方式互相告知自己的状态,以避免无效的资源争夺。

    线程间通信的方式可以有很多种:等待-通知、共享内存、管道流。“等待-通知”通信方式是Java中使用普遍的线程间通信方式,其经典的案例是“生产者-消费者”模式。

    2. 为什么需要wait-notify?

    场景:有几个小孩都想进入房间内使用算盘(CPU)进行计算,老王(操作系统)就使用了一把(synchronized)让同一时间只有一个小孩能进入房间使用算盘,于是他们排队进入房间。

    (1) 小南最先获取到了锁,进入到房间内,但是由于条件不满足(没烟干不了活),小南不能继续进行计算 ,但小南如果一直占用着锁,其它人就得一直阻塞,效率太低。

    Java线程通信中wait-notify通信的方式是什么

    (2) 于是老王单开了一间休息室(调用 wait 方法),让小南到休息室(WaitSet)等着去了,这时锁释放开, 其它人可以由老王随机安排进屋

    (3) 直到小M将烟送来,大叫一声 [ 你的烟到了 ] (调用 notify 方法)

    Java线程通信中wait-notify通信的方式是什么

    (4) 小南于是可以离开休息室,重新进入竞争锁的队列

    Java线程通信中wait-notify通信的方式是什么

    java语言中“等待-通知”方式的线程间通信使用对象的wait()、notify()两类方法来实现。每个java对象都有wait()、notify()两类实例方法,并且wait()、notify()方法和对象的监视器是紧密相关的。

    wait()、notify()两类方法在数量上不止两个。wait()、notify()两类方法不属于Thread类,而是属于java对象实例。

    3. wait方法和notify方法

    java对象中的wait()、notify()两类方法就如同信号开关,用于等待方和通知方之间的交互。

    1、对象的wait()方法

    对象的wait()方法的主要作用是让当前线程阻塞并等待被唤醒。wait()方法与对象监视器紧密相关,使用wait()方法时一定要放在同步块中。wait()方法的调用方法如下:

    public class Main {    static final Object lock = new Object();    public static void method1() throws InterruptedException {        synchronized( lock ) {            lock.wait();        }    }}

    Object类中的wait()方法有三个版本:

    (1) void wait():当前线程调用了同步对象lockwait()实例方法后,将导致当前的线程等待,当前线程进入lock的监视器WaitSet,等待被其他线程唤醒;

    (2) void wait(long timeout):限时等待。导致当前的线程等待,等待被其他线程唤醒,或者指定的时间timeout用完,线程不再等待;

    (3) void wait(long timeout,int nanos):高精度限时等待,其主要作用是更精确地控制等待时间。参数nanos是一个附加的纳秒级别的等待时间;

    2、对象的notify()方法

    对象的notify()方法的主要作用是唤醒在等待的线程。notify()方法与对象监视器紧密相关,调用notify()方法时也需要放在同步块中。notify()方法的调用方法如下:

    public class Main {    static final Object lock = new Object();    public static void method1() throws InterruptedException {        synchronized( lock ) {            lock.notify();        }    }}

    notify()方法有两个版本:

    (1)void notify()lock.notify()调用后,唤醒lock监视器等待集中的第一条等待线程;被唤醒的线程进入EntryList,其状态从WAITING变成BLOCKED。

    (2) void notifyAll()lock.notifyAll()被调用后,唤醒lock监视器等待集中的全部等待线程,所有被唤醒的线程进入EntryList,线程状态从WAITING变成BLOCKED。

    小结:

    obj.wait():让进入Object监视器的线程到waitset等待

    obj.notify():在Object上正在waitset等待的线程中挑一个唤醒

    obj.notifyAll():让在Object上正在waitset等待的线程全部唤醒

    4. wait方法和notify方法的原理

    对象的wait()方法的核心原理大致如下:

    (1) 当线程调用了lock(某个同步锁对象)的wait()方法后,JVM会将当前线程加入lock监视器的WaitSet(等待集),等待被其他线程唤醒。

    (2) 当前线程会释放lock对象监视器的Owner权利,让其他线程可以抢夺lock对象的监视器。

    (3) 让当前线程等待,其状态变成WAITING。在线程调用了同步对象lock的wait()方法之后,同步对象lock的监视器内部状态大致如图2-15所示。

    对象的notify()或者notifyAll()方法的原理大致如下:

    (1) 当线程调用了lock(某个同步锁对象)的notify()方法后,jvm会唤醒lock监视器WaitSet中的第一条等待线程。

    (2) 当线程调用了locknotifyAll()方法后,jvm会唤醒lock监视器WaitSet中的所有等待线程。

    (3) 等待线程被唤醒后,会从监视器的WaitSet移动到EntryList,线程具备了排队抢夺监视器Owner权利的资格,其状态从WAITING变成BLOCKED。

    (4) EntryList中的线程抢夺到监视器的Owner权利之后,线程的状态从BLOCKED变成Runnable,具备重新执行的资格。

    Java线程通信中wait-notify通信的方式是什么

    (1) Owner 线程发现条件不满足,调用wait 方法,即可进入WaitSet,变为 WAITING 状态 ;

    (2) BLOCKED 和WAITING 的线程都处于阻塞状态,不占用CPU时间片 ;

    (3) BLOCKED:线程会在Owner 线程释放锁时唤醒 ;

    (4) WAITING :线程会在Owner 线程调用notify 或 notifyAll时唤醒,但唤醒后并不意味者立刻获得锁,仍需进入 EntryList 重新竞争;

    5. wait方法和notify方法示例

    1、进入Object监视器的线程才能调用wait()方法

    小南并不能直接进入WaitSet休息室,而是获取锁进入房间后才能进入休息室,没有锁的话小南没法进入房间,更没法进入休息室。他进入休息室后就会释放锁,让其他线程竞争锁进入房间。

    Java线程通信中wait-notify通信的方式是什么

    public class Main {    static final Object lock = new Object();    public static void main(String[] args) {        synchronized (lock){            try {                // 只有成为了monitor对象的owner,即获得了对象锁之后,才有资格进入waitset等待                lock.wait();            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}

    2、进入Object监视器的线程才能调用notify()方法

    小M此时获取到了锁,进入了房间,并唤醒了在休息室中等待的小王,小M如果获取到锁进行房间时没有办法唤醒在休息室等待的小王的,因为此时小M在门外,小王根本听不到。

    Java线程通信中wait-notify通信的方式是什么

    使用notify()唤醒等待区的一个线程:

    public class Main {    static final Object lock = new Object();    public static void main(String[] args) throws InterruptedException {        Thread t1 = new Thread(()->{            System.out.println("t1线程开始执行...");            synchronized (lock){                try {                    // 让t1线程在lock锁的waitset中等待                    lock.wait();                } catch (InterruptedException e) {                    e.printStackTrace();                }                // 被唤醒后,继续执行                System.out.println("线程t1被唤醒...");            }        },"t1");        t1.start();        Thread t2 = new Thread(()->{            System.out.println("t2线程开始执行...");            synchronized (lock){                try {                    // 让t2线程在lock锁的waitset中等待                    lock.wait();                } catch (InterruptedException e) {                    e.printStackTrace();                }            }            // 被唤醒后,继续执行            System.out.println("线程t2被唤醒...");        },"t2");        t2.start();        Thread.sleep(2000);        System.out.println("唤醒lock锁上等待的线程...");        synchronized (lock){            // 主线程拿到锁后,唤醒正在休息室中等待的某一个线程            lock.notify();        }    }}

    执行结果:

    t1线程开始执行...
    t2线程开始执行...
    唤醒lock锁上等待的线程...
    线程t1被唤醒...

    使用notifyAll()唤醒等待区所有的线程:

    public class Main {    static final Object lock = new Object();    public static void main(String[] args) throws InterruptedException {        Thread t1 = new Thread(()->{            System.out.println("t1线程开始执行...");            synchronized (lock){                try {                    // 让t1线程在lock锁的waitset中等待                    lock.wait();                } catch (InterruptedException e) {                    e.printStackTrace();                }                // 被唤醒后,继续执行                System.out.println("线程t1被唤醒...");            }        },"t1");        t1.start();        Thread t2 = new Thread(()->{            System.out.println("t2线程开始执行...");            synchronized (lock){                try {                    // 让t2线程在lock锁的waitset中等待                    lock.wait();                } catch (InterruptedException e) {                    e.printStackTrace();                }            }            // 被唤醒后,继续执行            System.out.println("线程t2被唤醒...");        },"t2");        t2.start();        Thread.sleep(2000);        System.out.println("唤醒lock锁上等待的线程...");        synchronized (lock){            // 主线程拿到锁后,唤醒正在休息室中等待的所有线程            lock.notifyAll();        }    }}

    执行结果:

    t1线程开始执行...
    t2线程开始执行...
    唤醒lock锁上等待的线程...
    线程t2被唤醒...
    线程t1被唤醒...

    6. 为什么 wait 和 notify 方法要在同步块中调用?

    在调用同步对象的wait()和notify()系列方法时,“当前线程”必须拥有该对象的同步锁,也就是说,wait()和notify()系列方法需要在同步块中使用,否则JVM会抛出类似如下的异常:

    Java线程通信中wait-notify通信的方式是什么

    为什么wait和notify不在synchronized同步块的内部使用会抛出异常呢?这需要从wait()和notify()方法的原理说起。

    wait()方法的原理:

    首先,JVM会释放当前线程的对象锁监视器的Owner资格;其次,JVM会将当前线程移入监视器的WaitSet队列,而这些操作都和对象锁监视器是相关的。所以,wait()方法必须在synchronized同步块的内部调用。在当前线程执行wait()方法前,必须通过synchronized()方法成为对象锁的监视器的Owner。

    notify()方法的原理:

    JVM从对象锁的监视器的WaitSet队列移动一个线程到其EntryList队列,这些操作都与对象锁的监视器有关。所以,notify()方法也必须在synchronized同步块的内部调用。在执行notify()方法前,当前线程也必须通过synchronized()方法成为对象锁的监视器的Owner。

    关于“Java线程通信中wait-notify通信的方式是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注编程网精选频道,小编每天都会为大家更新不同的知识点。

    --结束END--

    本文标题: Java线程通信中wait-notify通信的方式是什么

    本文链接: https://www.lsjlt.com/news/323748.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    本篇文章演示代码以及资料文档资料下载

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档
    猜你喜欢
    • Java线程通信中wait-notify通信的方式是什么
      这篇文章主要介绍“Java线程通信中wait-notify通信的方式是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java线程通信中wait-notify通信的方式是什么”文章能帮助大家解决问...
      99+
      2023-06-29
    • Java线程通信之wait-notify通信方式详解
      目录1.线程通信的定义2.为什么需要wait-notify3.wait方法和notify方法1、对象的wait()方法2、对象的notify()方法4.wait方法和notify方法...
      99+
      2024-04-02
    • 浅谈Java线程间通信之wait/notify
      Java中的wait/notify/notifyAll可用来实现线程间通信,是Object类的方法,这三个方法都是native方法,是平台相关的,常用来实现生产者/消费者模式。先来我们来看下相关定义:wait() :调用该方法的线程进入WA...
      99+
      2023-05-31
      java 线程wait notify
    • Java如何使用wait/notify实现线程间通信
      本文小编为大家详细介绍“Java如何使用wait/notify实现线程间通信”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java如何使用wait/notify实现线程间通信”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习...
      99+
      2023-07-04
    • Java中怎么使用wait和notify实现线程间的通信
      这篇“Java中怎么使用wait和notify实现线程间的通信”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Java中怎么使...
      99+
      2023-06-30
    • Java怎么使用wait或notify实现线程间通信
      这篇文章主要介绍“Java怎么使用wait或notify实现线程间通信”,在日常操作中,相信很多人在Java怎么使用wait或notify实现线程间通信问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java怎...
      99+
      2023-07-04
    • Java使用wait和notify实现线程之间的通信
      目录一. 为什么需要线程通信二. wait和notify方法1. wait()方法2. notify()方法 3. notifyAll()方法三. 使用wait和notif...
      99+
      2024-04-02
    • Java通过wait()和notifyAll()方法实现线程间通信
      本文实例为大家分享了Java实现线程间通信的具体代码,供大家参考,具体内容如下Java代码(使用了2个内部类):package Threads;import java.util.LinkedList;public class ProdCon...
      99+
      2023-05-31
      java wait notifyall
    • Java线程间通信方式
      前文了解了线程的创建方式和状态切换,在实际开发时,一个进程中往往有很多个线程,大多数线程之间往往不是绝对独立的,比如说我们需要将A和B 两个线程的执行结果收集在一起然后显示在界面上,又或者比较典型的消...
      99+
      2023-09-24
      java jvm 开发语言 android
    • java线程间通信的方法是什么
      Java线程间通信的方法有以下几种: 使用共享变量:多个线程共享同一个变量,通过对变量的读写操作来实现线程间的通信。例如,一个线程...
      99+
      2023-10-28
      java
    • 浅谈Java线程间通信方式
      目录1.volatile和synchronized关键字2.等待/通知机制3.管道输入/输出流4.join()方法5.ThreadLocal()方法总结线程间通信方式有两种:共享内存...
      99+
      2024-04-02
    • 线程通信的四种方式
      多个线程在并发执行的时候,他们在CPU中是随机切换执行的,这个时候我们想多个线程一起来完成一件任务,这个时候我们就需要线程之间的通信了,多个线程一起来完成一个任务,线程通信一般有4种方式: 通过 vo...
      99+
      2023-09-05
      java
    • android多线程通信的方法是什么
      在Android中,多线程通信可以使用以下几种方法:1. Handler:Handler是用于在不同线程之间传递消息的机制。可以在主...
      99+
      2023-08-18
      android
    • Python进程间的通信方式是什么
      这篇文章主要介绍“Python进程间的通信方式是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Python进程间的通信方式是什么”文章能帮助大家解决问题。什么是进程的通信这里举一个例子接介绍通信...
      99+
      2023-06-29
    • Linux进程间通信的方式是什么
      本篇内容主要讲解“Linux进程间通信的方式是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Linux进程间通信的方式是什么”吧!·进程间通信:操作系统为系统提供的用于实现进程间通信的方式进...
      99+
      2023-06-29
    • Vue组件的通信方式是什么
      本篇内容主要讲解“Vue组件的通信方式是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Vue组件的通信方式是什么”吧!组件间通信的概念开始之前,我们把组件间通信这个词进行拆分组件通信都知道组...
      99+
      2023-07-06
    • Flutter web bridge通信方式是什么
      这篇文章主要介绍“Flutter web bridge通信方式是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Flutter web bridge通信方式...
      99+
      2023-07-05
    • java中TCP通信指的是什么
      小编给大家分享一下java中TCP通信指的是什么,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!Java的特点有哪些Java的特点有哪些1.Java语言作为静态面向对象编程语言的代表,实现了面向对象理论,允许程序员以优雅的思...
      99+
      2023-06-14
    • Java中怎么实现多线程通信
      Java中怎么实现多线程通信,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。概述多线程通信问题,也就是生产者与消费者问题生产者和消费者为两个线程,两个线程在运行过程中交替睡眠,生...
      99+
      2023-06-20
    • 怎么在java中实现线程通信
      本篇文章给大家分享的是有关怎么在java中实现线程通信,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。Java是什么Java是一门面向对象编程语言,可以编写桌面应用程序、Web应...
      99+
      2023-06-14
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作