zoukankan      html  css  js  c++  java
  • java 22

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

    接上一章的例子。

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

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

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

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

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

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

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

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

    * 测试类:StudentDemo

     1 public class StudentDemo {
     2     public static void main(String[] args) {
     3         //创建资源
     4         Student s = new Student();
     5         
     6         //设置和获取的类
     7         SetThread st = new SetThread(s);
     8         GetThread gt = new GetThread(s);
     9 
    10         //线程类
    11         Thread t1 = new Thread(st);
    12         Thread t2 = new Thread(gt);
    13 
    14         //启动线程
    15         t1.start();
    16         t2.start();
    17     }
    18 }

    来,依次分析这段代码:

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

    则先执行这段代码:

     1     public void run() {
     2         while (true) { //true,进来
     3             synchronized (s) {
     4                 if(!s.flag){ //因为是消费者先进来,所以里面没有“包子”,而s.flag的默认值是flase,这里取反,就true,进来
     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                 
    17                 s.notify(); 
    18             }
    19         }
    20     }

    ②由于消费者在等待,并且释放了锁。则消费者和生产者继续抢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继续抢到执行权:

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

    ④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 }
    何事都只需坚持.. 难? 维熟尔。 LZL的自学历程...只需坚持
  • 相关阅读:
    AndroidUI组件之ListView小技巧
    iframe属性參数
    Applet 数字签名技术全然攻略
    SoftReference
    递归算法浅谈
    VS2010 打包生成exe文件后 执行安装文件出现 TODO:<文件说明>已停止工作并已关闭
    创建新的Cocos2dx 3.0项目并解决一些编译问题
    ORACLE触发器具体解释
    SRM 624 D2L3: GameOfSegments, 博弈论,Sprague–Grundy theorem,Nimber
    cidaemon.exe进程cpu占用率高及关闭cidaemon.exe进程方法
  • 原文地址:https://www.cnblogs.com/LZL-student/p/5947623.html
Copyright © 2011-2022 走看看