一 java线程的等待/通知模型

九章 等级 705 0 0

java 中线程之间的通信问题,有这么一个模型:一个线程修改了一个对象的值,而另一个线程感知到了变化,然后进行相应的操作,整个过程开始于一个线程,而最终执行又是另一个线程。前者是生产者,后者就是消费者,也可以叫做生产者-消费者问题

生产者生产了产品,如何通知消费者?下面就介绍下java线程中的等待-通知机制。其它语言类似,自行研究。代码附上

下面是以买小米5手机为例子,来说明等待通知机制

/**
 * 买小米5手机
 * @author zhanghongjun
 *
 */
public class BuyXiaoMi5 {
    static boolean hasXiaoMi5 = false;
    static Object lock = new Object();

    public static void main(String[] args) throws InterruptedException {
        //消费者
        Thread miFansThread = new Thread(new MiFans(),"MiFans");

        //生产者
        Thread leiBS = new Thread(new LeiBuShi(),"LeiBuShi");

        miFansThread.start();
        leiBS.start();

    }

    /**
     * 雷布斯,生产者
     * @author zhanghongjun
     *
     */
    static class LeiBuShi implements Runnable{
        @Override
        public void run() {
            synchronized (lock) {
                System.out.println("Are you ok ? 我们开始生产小米5了,大家等一等啊");
                try {
                    System.out.println("Are you ok ? 小米5手机生产ing中,大家等一等啊");
                    Thread.sleep(3000); //6个月后,小米5终于上市了
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println("Are you ok? 小米5上市啦,大家可以哄抢啦");
                lock.notifyAll();    //通知所有的人,可以抢手机了
                hasXiaoMi5 = true;    //终于有小米5手机了
            }
        }

    }


    /**
     * 米粉,消费者
     * @author zhanghongjun
     *
     */
    static class MiFans implements Runnable{
        @Override
        public void run() {
            synchronized (lock) {
                //没有小米5手机,只有等待了
                while(!hasXiaoMi5){
                    System.out.println("雷军耍猴,不知道要等多久,才能买到小米5...");
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }

            System.out.println("我是米粉,终于买到一台发烧的小米5了,开森中。。。");
        }
    }

}

上面代码可以看到,开始的时候,米粉线程要买小米5手机,结果条件不满足,hasXiaoMi5 = false; 当条件不满足的时候,就需要等待, lock.wait();

此时线程进入等待队列中,线程会阻塞,需要注意 lock.wait() ,是会释放锁的,进而进入到线程的等待队列中,这时候,因为wait()已经释放了锁,所以,LeiBuShi 线程就可以

获得锁,进而去生产手机,等到手机生产出来以后,既 hasXiaoMi5 = true了,这时候就通知在此锁上等待的线程,lock.notify()或者lock.notifyAll,之后,离开同步块,进而释放锁,这时候 61行,lock.wait() 函数返回,条件成立,进而继续向下运行,买到手机。

这里需要注意的几点如下:

1 使用wait(),notify(),notifyAll()时需要先对调用对象加锁

2 调用wait()方法后,线程状态由Running状态变为 waiting状态,并将当前线程放置到线程的等待队列中

3 notify()或者notifyAll()方法调用后,等待线程依旧不会从wait()返回,需要调用notify()或者nofityAll()的线程释放锁之后,等待线程才有机会从wait()返回

4 从wait()方法返回的前提是获得了调用对象的锁.

等待/通知的经典范式

等待方步骤如下:

1 获取对象的锁

2 如果条件满足,那么调用对象的wait()方法,被通知后仍要检查条件。

3 条件满足则执行相应的业务逻辑

对应的伪代码如下:

synchronized(对象){

  while(条件不满足时){

        对象.wait()

  }

     对应的逻辑

}

通知方步骤如下:

1 获得对象的锁

2 改变条件

3 通知所有等待对象上的线程

对应的伪代码如下:

synchronized(对象){

  改变条件

  对象.notifyAll()

}

以上就是典型的通知等待机制。能力有限,希望对大家有所帮助

收藏
评论区

相关推荐

JAVA NIO(一)
**1 NIO概述** 1.1NIO(new IO)是一个可以替代java IO API的API,NIO提供了与标准IO不同的工作方式,标准IO是基于字节流和字符流进行操作的,而NIO是基于channel和Buffer进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写到通道中,方式如例图示,JAVA NIO的几个核心组成部分是channels,Buf
Java 基础 SDK区别简介
1. Java SE(Java Platform,Standard Edition),应该先说这个,因为这个是标准版本。 Java EE (Java Platform,Enterprise Edition),java 的企业版本 Java ME(Java Platform,Micro Edition),java的微型版本。 1). JavaSE 可以
Java 高级应用编程 第一章 工具类
**一、Java API** **Java API简介** 1、API (Application Programming Interface) 应用程序接口 2、Java中的API,就是JDK提供的各种功能的Java类 3、JDK帮助文档   JAVA\_API\_CN.chm   官网地址http://www.oracle.com/tech
Java入门篇(一)——如何编写一个简单的Java程序
  最近准备花费很长一段时间写一些关于Java的从入门到进阶再到项目开发的教程,希望对初学Java的朋友们有所帮助,更快的融入Java的学习之中。   主要内容包括JavaSE、JavaEE的基础知识以及如何用Java语言编写一个简单的软件、一个小型的游戏、一个简易的项目、或者一些比较复杂的项目实战等等。   这些文章我不准备用概念来引入Java知识,因
Java环境设置JDK为例
**环境设置分三步:安装前准备;安装;环境设置及测试。** * * * 一、安装前准备 了解一下需要安装的都是什么:Java是由Sun Microsystems公司于1995年5月推出的Java面向对象程序设计语言和Java平台的总称。由James Gosling和同事们共同研发,并在1995年正式推出。且Java包括三个平台版本,分别为Java SE
Java的JDK到底是什么?Java JDK小白安装教程(win10)!
小白的Java JDK安装教程(win10): ----------------------- Java JDK安装3步走,手把手教小白安装Java JDK! * **Java JDK**是干什么用的?如何安装? * 安装完 Java JDK 为什么要设置**环境变量**? * 如何设置Java JDK 环境变量 一、Java JDK 是干
Java的泛型详解(一)
Java的泛型详解(一) 编写的代码可以被不同类型的对象所重用。 因为上面的一个优点,泛型也可以减少代码的编写。 1|2泛型的使用 简单泛型类 public class Pair { private T first; private T second; public Pair() { first = null; second = null;
Java,传奇的一生!
 如果说用“永存、曲折、已死、重生”来形容Java,笔者以为一点也不为过。 1991年,James Gosling带领着名为“Green Team”的团队着手研发一种新的语言以及专为下一代数字设备和计算机使用的网络系统。历时4年辛勤工作后,该项目最终修成正果并取名为Java。  Java有着类似于C的语法并有“一次编译,随处运行”的灵便性。透过虚拟机机制
java04eclipse常见设置和java的第一个程序、命名规范、编码规范
一、java的第一个程序 \*所有的java程序是写在.java为后缀的文本 \*所有的java程序一定是写在class中   即写在类里面的 \*所有的java程序的入口一定是main方法 \*写代码 二、新建一个java项目 《1》新建一个java工程 《2》在src下建包 《3》在包下面新建java文件 《4》所有java代码是在写类
java入门
一) Java言语入门教程Java类的组成一向很喜欢一句广告词:日子即是一个七天又一个七天。而我想说的是,Java运用就是一个类又一个类。Java是面向目标的言语,目标都是由类实例化而来。一个Java运用,不管简略仍是杂乱,都是由若干个Java类组成的。因而,关于初学者,先知道Java类的组成是必要的。 Java类的组成首要有3有些:数据成员、结构办法、办
java基础知识随身记
2018年11月12日20:51:35 一、基础知识: 1、JVM、JRE和JDK的区别: JVM(Java Virtual Machine):java虚拟机,用于保证java的跨平台的特性。   java语言是跨平台,jvm不是跨平台的。 JRE(Java Runtime Environment):java的运行环境,包括jvm+java的核心类
java的特性
java的特性 ======= 1、Java语言是简单的 2、Java语言是面向对象的 3、Java语言是分布式的 4、Java语言是健壮的 5、Java语言是安全的 6、Java语言是可移植性的 7、Java语言是解释型的 8、Java语言是多线程的 9、Java语言是动态的语言   **Java语言是简单的:**  
Ubuntu中,关于的Java一切
1.安装Java ----------- ppa仓库:[https://launchpad.net/~webupd8team/+archive/ubuntu/java](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Flaunchpad.net%2F%7Ewebupd8team%2F
Unsafe -- Java的魔法类(一)
Unsafe Java的魔法类(一)::: tip 原创不易,转载请注明来源::: 一、简介​ Unsafe,顾名思义,不安全的;Unsafe类位于sun.misc包下,执行低级、不安全操作的方法集合。对于号称是安全的编程语言Java来说,无疑它是个例外,不仅仅是因为它可以堆内存进行操作,还是通过非常规化手段获取到对象,还是对线程调度毛手毛脚,总是它不属
Linux中查看jdk安装目录、Linux卸载jdk、rpm命令、rm命令参数
一、查看jdk安装目录 ----------- [root@node001 ~]# whereis java java: /usr/bin/java /usr/local/java #java执行路径 [root@node001 ~]# which java /usr/bin/java #查看JDK安装路径