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

接上一章的例子。

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

  * 资源类: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. SharePoint 2013 Error - File names can't contain the following characters: & " ? < > # {} % ~ / \.

    错误截图: 错误信息: --------------------------- Message from webpage --------------------------- File names ...

  2. SharePoint 2013 开发文档管理字段小记

    前言 最近有这样一个需求,就是要求在列表库里管理文档,需要多文档管理.带版本控制.可以单独授权等基本操作.于是乎,就开发了一个自定义段,这里介绍一下字段的思路,里面有一些遇到的问题,在群友的帮助下已解 ...

  3. 转:ibatis常用16条SQL语句

    1.输入参数为单个值 <delete id="com.fashionfree.stat.accesslog.deleteMemberAccessLogsBefore" par ...

  4. 如何处理 android 方法总数超过 65536 . the number of method references in a .dex file exceed 64k

    一:问题描述:     应用中的Dex 文件方法数超过了最大值65536的上限,简单来说,应用爆棚了. 二.解决方案:      方案1:使用插件化框架  比如: https://github.com ...

  5. 【代码笔记】iOS-点评内容

    一,效果图. 二,工程图. 三,代码. ViewController.h #import <UIKit/UIKit.h> @interface ViewController : UIVie ...

  6. 手机屏幕滑动效果框架——flipsnap

    下午有时间,研究了下手机网页开发方面的内容.其中关于手机手势滑屏操作.发现有比较好的jquery 插件--flipsnap. 官方网站:http://pxgrid.github.com/js-flip ...

  7. C#语句1:选择语句二(switch break)

    (二)switch case switch case 必须与 break 一同使用.break是跳转语句.与switch case连用的时候是跳出最近的{}. 注: ●若case后面接收的是字符串类型 ...

  8. mysql多实例的配置和管理

    原文地址:mysql多实例的配置和管理 作者:飞鸿无痕 多实例mysql的安装和管理 mysql的多实例有两种方式可以实现,两种方式各有利弊.第一种是使用多个配置文件启动不同的进程来实现多实例,这种方 ...

  9. JDK动态代理和CGLIB的区别

    Aspect默认情况下不用实现接口,但对于目标对象,在默认情况下必须实现接口 如果没有实现接口必须引入CGLIB库 我们可以通过Advice中添加一个JoinPoint参数,这个值会由spring自动 ...

  10. 深入理解Nginx之调试优化技巧

    在开发过程中,我们经常会碰到段错误等异常,这时我们需要有相应的机制来进行调试,特别是服务提供在线上时,面对大量的日志信息,合理的调试处理机制对于开发来说是一件非常重要的事情,幸好Nginx本身提供了很 ...