1. 首先我们根据梳理我们之前Android(java)学习笔记70中,关于生产者和消费者程序思路:

2. 下面我们就要重点介绍这个等待唤醒机制:

(1)第一步:还是先通过代码体现出等待唤醒机制

下面是测试类:

package cn.itcast_05;

/*
* 分析:
* 资源类:Student
* 设置学生数据:SetThread(生产者)
* 获取学生数据:GetThread(消费者)
* 测试类:StudentDemo
*
* 问题1:按照思路写代码,发现数据每次都是:null---0
* 原因:我们在每个线程中都创建了新的资源,而我们要求的时候设置和获取线程的资源应该是同一个
* 如何实现呢?
* 在外界把这个数据创建出来,通过构造方法传递给其他的类。
*
* 问题2:为了数据的效果好一些,我加入了循环和判断,给出不同的值,这个时候产生了新的问题
* A:同一个数据出现多次
* B:姓名和年龄不匹配
* 原因:
* A:同一个数据出现多次
* CPU的一点点时间片的执行权,就足够你执行很多次。
* B:姓名和年龄不匹配
* 线程运行的随机性
* 线程安全问题:
* A:是否是多线程环境 是
* B:是否有共享数据 是
* C:是否有多条语句操作共享数据 是
* 解决方案:
* 加锁。
* 注意:
* A:不同种类的线程都要加锁。
* B:不同种类的线程加的锁必须是同一把。
*
* 问题3:虽然数据安全了,但是呢,一次一大片不好看,我就想依次的一次一个输出。
* 如何实现呢?
* 通过Java提供的等待唤醒机制解决。
*
* 等待唤醒:
* Object类中提供了三个方法:
* wait():等待
* notify():唤醒单个线程
* notifyAll():唤醒所有线程
* 为什么这些方法不定义在Thread类中呢?
* 这些方法的调用必须通过锁对象调用,而我们刚才使用的锁对象是任意锁对象。
* 所以,这些方法必须定义在Object类中。
*/
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();
}
}

 下面是生产者线程类:

 package cn.itcast_05;

 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 = 27;
} else {
s.name = "刘意";
s.age = 30;
}
x++; //x=1 //修改标记
s.flag = true;
//唤醒线程
s.notify(); //唤醒t2,唤醒并不表示你立马可以执行,必须还得抢CPU的执行权。
}
//t1有,或者t2有
}
}
}

 下面是消费者线程类:

 package cn.itcast_05;

 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);
//林青霞---27
//刘意---30 //修改标记
s.flag = false;
//唤醒线程
s.notify(); //唤醒t1
}
}
}
}

 Student类:

 package cn.itcast_05;

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

 

(2)接下来我们对唤醒机制代码进行优化:

下面是测试类:

 package cn.itcast_07;

 /*
* 分析:
* 资源类:Student
* 设置学生数据:SetThread(生产者)
* 获取学生数据:GetThread(消费者)
* 测试类:StudentDemo
*
* 问题1:按照思路写代码,发现数据每次都是:null---0
* 原因:我们在每个线程中都创建了新的资源,而我们要求的时候设置和获取线程的资源应该是同一个
* 如何实现呢?
* 在外界把这个数据创建出来,通过构造方法传递给其他的类。
*
* 问题2:为了数据的效果好一些,我加入了循环和判断,给出不同的值,这个时候产生了新的问题
* A:同一个数据出现多次
* B:姓名和年龄不匹配
* 原因:
* A:同一个数据出现多次
* CPU的一点点时间片的执行权,就足够你执行很多次。
* B:姓名和年龄不匹配
* 线程运行的随机性
* 线程安全问题:
* A:是否是多线程环境 是
* B:是否有共享数据 是
* C:是否有多条语句操作共享数据 是
* 解决方案:
* 加锁。
* 注意:
* A:不同种类的线程都要加锁。
* B:不同种类的线程加的锁必须是同一把。
*
* 问题3:虽然数据安全了,但是呢,一次一大片不好看,我就想依次的一次一个输出。
* 如何实现呢?
* 通过Java提供的等待唤醒机制解决。
*
* 等待唤醒:
* Object类中提供了三个方法:
* wait():等待
* notify():唤醒单个线程
* notifyAll():唤醒所有线程
* 为什么这些方法不定义在Thread类中呢?
* 这些方法的调用必须通过锁对象调用,而我们刚才使用的锁对象是任意锁对象。
* 所以,这些方法必须定义在Object类中。
*
* 最终版代码中:
* 把Student的成员变量给私有的了。
* 把设置和获取的操作给封装成了功能,并加了同步。
* 设置或者获取的线程里面只需要调用方法即可。
*/
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();
}
}

 生产者线程类:

 package cn.itcast_07;

 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) {
if (x % 2 == 0) {
s.set("林青霞", 27);
} else {
s.set("刘意", 30);
}
x++;
}
}
}

 消费者线程类:

 package cn.itcast_07;

 public class GetThread implements Runnable {
private Student s; public GetThread(Student s) {
this.s = s;
} @Override
public void run() {
while (true) {
s.get();
}
}
}

 Student类,同时Student内部封装了Student的两个同步方法(生产Student  和  消费Student)

 package cn.itcast_07;

 public class Student {
private String name;
private int age;
private boolean flag; // 默认情况是没有数据,如果是true,说明有数据 public synchronized void set(String name, int age) {
// 如果有数据,就等待
if (this.flag) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} // 设置数据
this.name = name;
this.age = age; // 修改标记
this.flag = true;
this.notify();
} public synchronized void get() {
// 如果没有数据,就等待
if (!this.flag) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} // 获取数据
System.out.println(this.name + "---" + this.age); // 修改标记
this.flag = false;
this.notify();
}
}

 

3. sleep和wait的区别有:

(1)这两个方法来自不同的类,分别是Thread和Object
(2)最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
(3)wait,notify 和 notifyAll 只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用
   synchronized(x){
        x.notify()
       //或者wait()
   }

(4)sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常

Android(java)学习笔记71:生产者和消费者之等待唤醒机制的更多相关文章

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

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

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

    二.生产者消费者模式的学生类成员变量生产与消费demo, @Version2.0 在学生类中添加同步方法:synchronized get()消费者,synchronized set()生产者 最终版 ...

  3. Android(java)学习笔记11:生产者和消费者之等待唤醒机制

    1. 首先我们根据梳理我们之前Android(java)学习笔记70中,关于生产者和消费者程序思路: 2. 下面我们就要重点介绍这个等待唤醒机制: (1)第一步:还是先通过代码体现出等待唤醒机制 下面 ...

  4. java ->多线程_线程同步、死锁、等待唤醒机制

    线程安全 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的. l  我们通过一个案例,演示线 ...

  5. 2.5多线程(Java学习笔记)生产者消费者模式

    一.什么是生产者消费者模式 生产者生产数据存放在缓冲区,消费者从缓冲区拿出数据处理. 可能大家会问这样有何好处? 1.解耦 由于有了缓冲区,生产者和消费者之间不直接依赖,耦合度降低,便于程序拓展和维护 ...

  6. java多线程(死锁,lock接口,等待唤醒机制)

    一.Lock接口 常用方法 Lock提供了一个更加面对对象的锁,在该锁中提供了更多的操作锁的功能. 使用Lock接口,以及其中的lock()方法和unlock()方法替代同步,对电影院卖票案例中Tic ...

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

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

  8. java之等待唤醒机制(线程之间的通信)

    线程间通信 概念:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同.比如:线程A用来生成包子的,线程B用来吃包子的,包子可以理解为同一资源,线程A与线程B处理的动作,一个是生产,一个是消 ...

  9. java学习笔记之基础篇

    java选择语句之switch   //switch可以用于等值判断 switch (e) //int ,或则可以自动转化成int 的类型,(byte char short)枚举jdk 7中可以防止字 ...

随机推荐

  1. Windows服务-手把手带你体验

    Microsoft Windows 服务(即,以前的 NT 服务)使您能够创建在它们自己的 Windows 会话中可长时间运行的可执行应用程序.这些服务可以在计算机启动时自动启动,可以暂停和重新启动而 ...

  2. 20150913K-means聚类

    1.聚类的思想: 将一个有N个对象的数据集,构造成k(k<=n)个划分,每个划分代表一个簇.使得每个簇包含一个对象,每个对象有且仅属于一个簇.对于给定的k,算法首先给出一个初始的划分方法,以后通 ...

  3. 非常实用的Ubuntu常用终端命令

    先介绍关于文件和目录的命令: ls 列出当前目录文件(不包括隐含文件) ls -a 列出当前目录文件(包括隐含文件) ls -l 列出当前目录下文件的详细信息 cd .. 回当前目录的上一级目录 cd ...

  4. struts2+Hibernate4+spring3+EasyUI环境搭建之五:引入jquery easyui

    1.下载jquery easyui组件     http://www.jeasyui.com/download/index.php 2.解压 放到工程中  如图 3.jsp引入组件:必须按照如下顺序 ...

  5. [iOS基础控件 - 6.10] Notification 通知机制

    A.定义      iOS程序都有一个NSNotificationCenter的单例对象,用来负责发布不同对象之间的通知      任何对象都能够在NSNotificationCenter发布通知,发 ...

  6. js正则验证手机号

    var regp = /^(\+86|86|)1[3458][0-9]{9}$/; if(str==""){ var flag = checkstatus(obj,"&q ...

  7. 340. Longest Substring with At Most K Distinct Characters

    最后更新 二刷 08-Jan-2017 和76.159很像.. 2 pointers.. 通过判断是否每一次是有效读取来增减accumulator,从而判断当前是否符合规定,再来更新maxLength ...

  8. 创建类模式(二):抽象工厂(Abstract Factory)

    定义 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类. 抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态.抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式. ...

  9. 让div变得大方美观 bootstrap

    <div class="panel panel-default "> <div class="panel-heading"> <h ...

  10. Java学习备忘录

    1.工程名首字母可以小写,类名首字母大写 2.批量注释: Eclipse : ctrl+/  如果不行 用 ctrl+7 或者 ctrl+shift+c Notepad++ : ctrl+q 或者 c ...