先来一张图,看看什么叫做等待唤醒机制

接上一章的例子。

例子:学生信息的录入和获取

  * 资源类:Student 
  * 设置学生数据:SetThread(生产者)
  * 获取学生数据:GetThread(消费者)
  * 测试类:StudentDemo

* 资源类:Student (为了使用等待唤醒机制,添加了个布尔类型的变量,默认为flase)

 public class Student {
String name;
int age;
boolean flag; // 默认情况是没有数据,如果是true,说明有数据
}

* 设置学生数据:SetThread(生产者)

 public class SetThread implements Runnable {

     private Student s;
private int x = 0; public SetThread(Student s) {
this.s = s;
} @Override
public void run() {
while (true) {
synchronized (s) {
//判断有没有
if(s.flag){
try {
s.wait(); //t1等着,释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
} if (x % 2 == 0) {
s.name = "张三";
s.age = 23;
} else {
s.name = "李四";
s.age = 24;
}
x++; //x=1 //修改标记
s.flag = true;
//唤醒线程
s.notify(); //唤醒t2,唤醒并不表示你立马可以执行,必须还得抢CPU的执行权。
}
//t1有,或者t2有
}
}
}

* 获取学生数据:GetThread(消费者)

 public class GetThread implements Runnable {
private Student s; public GetThread(Student s) {
this.s = s;
} @Override
public void run() {
while (true) {
synchronized (s) {
if(!s.flag){
try {
s.wait(); //t2就等待了。立即释放锁。将来醒过来的时候,是从这里醒过来的时候
} catch (InterruptedException e) {
e.printStackTrace();
}
} System.out.println(s.name + "---" + s.age);
//张三---23
//李四---24 //修改标记
s.flag = false;
//唤醒线程
s.notify(); //唤醒t1
}
}
}
}

* 测试类:StudentDemo

 public class StudentDemo {
public static void main(String[] args) {
//创建资源
Student s = new Student(); //设置和获取的类
SetThread st = new SetThread(s);
GetThread gt = new GetThread(s); //线程类
Thread t1 = new Thread(st);
Thread t2 = new Thread(gt); //启动线程
t1.start();
t2.start();
}
}

来,依次分析这段代码:

①假设消费者GetThread先抢到了CPU的资源:

则先执行这段代码:

     public void run() {
while (true) { //true,进来
synchronized (s) {
if(!s.flag){ //因为是消费者先进来,所以里面没有“包子”,而s.flag的默认值是flase,这里取反,就true,进来
try {
s.wait(); //没“包子”,等待,并且释放锁。下次唤醒它的时候,是从这里唤醒,并不是从头开始执行
} catch (InterruptedException e) {
e.printStackTrace();
}
} System.out.println(s.name + "---" + s.age); s.flag = false; s.notify();
}
}
}

②由于消费者在等待,并且释放了锁。则消费者和生产者继续抢CPU的资源,而消费者抢到的话,依旧等待,直到生产者(SetThread)抢到CPU的资源:

    public void run() {
while (true) {
synchronized (s) { if(s.flag){//判断有没有“包子”,这时候是没有的,s.flag = false,执行下面的if语句
try {
s.wait(); //t1等着,释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//首先x = 0,先录入张三
if (x % 2 == 0) {
s.name = "张三";
s.age = 23;
} else {
s.name = "李四";
s.age = 24;
}
x++; //x=1
//这时候已经有“包子”了,就修改标志
s.flag = true;
//唤醒线程
s.notify(); //唤醒t2,唤醒并不表示你立马可以执行,必须还得抢CPU的执行权。
}
//t1继续抢到执行权,或者t2抢到执行权
}
}

③若是t1继续抢到执行权:

   synchronized (s) {

                 if(s.flag){//这个时候已经有了张三这个“包子”,而且flag = true;,所以进来
try {
s.wait(); //t1等待,并且释放锁,t1和t2抢占CPU资源,t1抢到继续等待,t2抢到就执行t2
} catch (InterruptedException e) {
e.printStackTrace();
}
}

④t2抢到执行权:

1     public void run() {
2 while (true) { //true,进来
3 synchronized (s) {
4 if(!s.flag){ //有“包子”,这时候的flag = true ,!s.flag = flase;不进来
5 try {
6 s.wait();
7 } catch (InterruptedException e) {
8 e.printStackTrace();
9 }
10 }
11 //消费“包子”
12 System.out.println(s.name + "---" + s.age);
13
14 //修改标记
15 s.flag = false;
16 //唤醒线程t1
17 s.notify();
18 }
          //唤醒t1,唤醒并不表示你立马可以执行,必须还得抢CPU的执行权。
19 } 
20 }

java 22 - 17 多线程之等待唤醒机制(接16)的更多相关文章

  1. java基础知识回顾之java Thread类学习(八)--java多线程通信等待唤醒机制经典应用(生产者消费者)

     *java多线程--等待唤醒机制:经典的体现"生产者和消费者模型 *对于此模型,应该明确以下几点: *1.生产者仅仅在仓库未满的时候生产,仓库满了则停止生产. *2.消费者仅仅在有产品的时 ...

  2. java基础知识回顾之java Thread类学习(七)--java多线程通信等待唤醒机制(wait和notify,notifyAll)

    1.wait和notify,notifyAll: wait和notify,notifyAll是Object类方法,因为等待和唤醒必须是同一个锁,不可以对不同锁中的线程进行唤醒,而锁可以是任意对象,所以 ...

  3. Java第二十五天,多线程之等待唤醒机制

    当线程被创建并且被启动之后,它既不是一启动就进入了执行状态,也不是一直处于执行状态,而是具有以下多种状态: 这六种状态之间的转换关系如下: 1.等待唤醒机制 注意: (1)两个线程之间必须用同步代码块 ...

  4. java多线程的等待唤醒机制及如何解决同步过程中的安全问题

    /* class Person{ String name; String sex; boolean flag = true; public void setPerson(String name, St ...

  5. java多线程中的生产者与消费者之等待唤醒机制@Version1.0

    一.生产者消费者模式的学生类成员变量生产与消费demo,第一版1.等待唤醒:    Object类中提供了三个方法:    wait():等待    notify():唤醒单个线程    notify ...

  6. JAVA之旅(十四)——静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制

    JAVA之旅(十四)--静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制 JAVA之旅,一路有你,加油! 一.静态同步函数的锁是clas ...

  7. Java多线程02(线程安全、线程同步、等待唤醒机制)

    Java多线程2(线程安全.线程同步.等待唤醒机制.单例设计模式) 1.线程安全 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运行结果和单线程运行的结果是一样的,而且其他的变量 ...

  8. “全栈2019”Java多线程第三十二章:显式锁Lock等待唤醒机制详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  9. “全栈2019”Java多线程第二十四章:等待唤醒机制详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

随机推荐

  1. 通过Map 3D API读取线状要素的节点坐标

    By Daniel Du 在Map 3D中可以使用Create from Geometry命令把AutoCAD实体转换成Map 3D中的FDO要素,比如可以把AutoCAD的polyline转换成FD ...

  2. Android Testing学习02 HelloTesting 项目建立与执行

    Android Testing学习02 HelloTesting 项目建立与执行 Android测试,分为待测试的项目和测试项目,这两个项目会生成两个独立的apk,但是内部,它们会共享同一个进程. 下 ...

  3. iOS自动布局进阶用法

    本文主要介绍几个我遇到并总结的相对高级的用法(当然啦牛人会觉得这也不算什么). 简单的storyboard中上下左右约束,固定宽高啥的用法在这里就不做赘述了. autolayout自动布局是iOS6以 ...

  4. Android 短视频拍摄、拍照滤镜 第三方库SDK

    视频 1.趣拍云服务 http://vcs.qupai.me/ 拍照 1.camera360 SDk 拍照滤镜 http://www.camera360.com/ 2 .凃图 http://tusdk ...

  5. 安装和使用cocoapods

    第一步:查看自己电脑的Ruby环境:gem sources -l 1.如果已经是taobao镜像了[https://ruby.taobao.org/],此时不需要环境的修改了,直接进入第二步 2.(1 ...

  6. iOS之 C++与oc混编

    声明:本文只是随笔,自己做个笔记方便以后查阅如要转载,注明出处.谢谢! 2016年第一篇随笔!!! 由于最近要搞一个项目用到c++的一些api所以要混编,于是就记录下这个过程中的一些细节上的东西! O ...

  7. .net开发过程中遇到的错误,及解决办法记录

    一.在证书存储区中找不到清单签名证书. 解决方法:右击项目属性—>签名—>为ClickOnce清单签名,将勾掉的选项去掉. 参考:http://www.cnblogs.com/190196 ...

  8. EMD_MAINTENANCE.EXECUTE_EM_DBMS_JOB_PROCS的删除创建

    在最近的一次优化过程中发现了ORACLE 10g中一个作业EMD_MAINTENANCE.EXECUTE_EM_DBMS_JOB_PROCS执行相当频繁,其实以前也看到过,只是没有做过多的了解和关注. ...

  9. python之装饰器

    一.简单装饰器: #定义装饰器函数 def W1(main_func): def outer(): print("before") main_func() print(" ...

  10. Html5拖拽复制

    拖拽是一种常见的特性,即抓取对象以后拖到另一个位置. 在 HTML5 中,拖拽是标准的一部分,任何元素都能够拖拽. Html5拖拽非常常见的一个功能,但是大部分拖拽的案例都是一个剪切的过程, 项目中需 ...