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

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

技术分享

 

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

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

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();
    }
}

 

 1 package cn.itcast_05;
 2 
 3 public class SetThread implements Runnable {
 4 
 5     private Student s;
 6     private int x = 0;
 7 
 8     public SetThread(Student s) {
 9         this.s = s;
10     }
11 
12     @Override
13     public void run() {
14         while (true) {
15             synchronized (s) {
16                 //判断有没有
17                 if(s.flag){
18                     try {
19                         s.wait(); //t1等着,释放锁
20                     } catch (InterruptedException e) {
21                         e.printStackTrace();
22                     }
23                 }
24                 
25                 if (x % 2 == 0) {
26                     s.name = "林青霞";
27                     s.age = 27;
28                 } else {
29                     s.name = "刘意";
30                     s.age = 30;
31                 }
32                 x++; //x=1
33                 
34                 //修改标记
35                 s.flag = true;
36                 //唤醒线程
37                 s.notify(); //唤醒t2,唤醒并不表示你立马可以执行,必须还得抢CPU的执行权。
38             }
39             //t1有,或者t2有
40         }
41     }
42 }

 

 1 package cn.itcast_05;
 2 
 3 public class GetThread implements Runnable {
 4     private Student s;
 5 
 6     public GetThread(Student s) {
 7         this.s = s;
 8     }
 9 
10     @Override
11     public void run() {
12         while (true) {
13             synchronized (s) {
14                 if(!s.flag){
15                     try {
16                         s.wait(); //t2就等待了。立即释放锁。将来醒过来的时候,是从这里醒过来的时候
17                     } catch (InterruptedException e) {
18                         e.printStackTrace();
19                     }
20                 }
21                 
22                 System.out.println(s.name + "---" + s.age);
23                 //林青霞---27
24                 //刘意---30
25                 
26                 //修改标记
27                 s.flag = false;
28                 //唤醒线程
29                 s.notify(); //唤醒t1
30             }
31         }
32     }
33 }

 

1 package cn.itcast_05;
2 
3 public class Student {
4     String name;
5     int age;
6     boolean flag; // 默认情况是没有数据,默认是false,如果是true,说明有数据
7 }

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。