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


     一、生产者消费者模式的学生类成员变量生产与消费demo,第一版
    1、等待唤醒:
          Object类中提供了三个方法:
          wait():等待
          notify():唤醒单个线程
          notifyAll():唤醒所有线程
    2、为什么这些方法不定义在Thread类中呢?
         这些方法的调用必须通过锁对象调用,而我们刚才使用的锁对象是任意锁对象。
        所以,这些方法必须定义在Object类中。
    3、当我们在使用多线程的时候有的时候需要,一条线程产生一个数据,另一条线程接着消费一个数据,一边生产一边消费,既没有多余的数据产生,也没有的空的数据被消费。

    4、问题解决方案第一步保证线程同步安全:(1)加锁,

        A:不同种类的线程都要加锁。
        B:不同种类的线程加的锁必须是同一把。

    5、问题解决方案第二步保证数据的一次生产消费:(等待唤醒机制)。

    6、在下面新建的两条线程,两条线程操作的对象都是学会类,一条线程生产学生对象的数据,一条线程消费学生对象的数据,且做到,有数据才消费,没数据就等待,没数据就生产,有数据就等待。

    //==========================

    //第一个案例是学生类对象,非常的简单就定义了两个成员变量,以及一个用于唤醒线程的标记。

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

    //下面的是生产者学生对象的demo

    //在构造方法中传递了学生对象,保证生产者与消费者操作的是同一个对象。

     1 public class setThread implements Runnable {
     2     private Student s;
     3     int x = 0;
     4 
     5     public setThread(Student s) {
     6         this.s = s;
     7     }
     8 
     9     @Override
    10     public void run() {
    11         while (true) {
    12             synchronized (s) {
    13                 // 唤醒机制,生产者,先判断有没有哦,有就等待被消费,没有就生产数据准备被消费。
    14                 if (s.flag) {
    15                     try {
    16                         s.wait();
    17                     } catch (InterruptedException e) {
    18                         // TODO Auto-generated catch block
    19                         e.printStackTrace();
    20                     }
    21                 }
    22                 
    23                 //一旦flag标记为false就执行下面的代码
    24                 
    25                 if (x % 2 == 0) {
    26                     s.name = "java";
    27                     s.age = 25;
    28                 } else {
    29                     s.name = "android";
    30                     s.age = 20;
    31                 }
    32                 x++;
    33                 // 数据生产一次,此时有了数据需要修改标记,下一循环开始的时候,就暂时不在生产,
    34                 s.flag = true;
    35 
    36                 // 唤醒线程
    37                 s.notify();
    38             }
    39 
    40         }
    41     }
    42 
    43 }

    //下面的是学生对象的消费者模式demo

    //在构造方法中传递了学生对象,保证生产者与消费者操作的是同一个对象。

     1 public class getThread implements Runnable {
     2     private Student s;
     3 
     4     public getThread(Student s) {
     5         this.s = s;
     6     }
     7 
     8     public void run() {
     9         while (true) {
    10             // 唤醒机制 消费者,有数据就消费,没有数据(!)就等待数据被生产。
    11             // 吐过没有就等待,有就消费
    12             synchronized (s) {
    13                 if (!s.flag) { //flag--->false执行if下面的代码:表示没有数据就等待
    14                     try {
    15                         s.wait();  //在等待的时候立即释放锁,方便其他的线程使用锁。而且被唤醒时,就在此处唤醒,
    16                     } catch (InterruptedException e) {
    17                         // TODO Auto-generated catch block
    18                         e.printStackTrace();
    19                     }
    20                 }
    21 
    22                 // flag--->true:消费数据
    23                 System.out.println(s.name + "   " + s.age);
    24                 // 消费完毕后,数据没有了,修改标记
    25                 s.flag = false;
    26                 // 唤醒线程
    27                 //唤醒并不代表你立即可以得到执行权,此时仍然需要抢CPU的执行权,
    28                 s.notify();   
    29             }
    30         }
    31     }
    32 }

    //下面的是测试用例,就是简单的创建了两条线程,然后启动刚才的生产者与消费者

     1 /*
     2  * 如何在同一个包下,多个类中共享一个数据:
     3  *         在外界把这个数据创建出来,然后通过构造方法传递给其它的类。
     4  */
     5 public class Demo {
     6     public static void main(String[] args) {
     7         // 共享数据,外界创建,作为参数,通过构造共有
     8         Student s = new Student();
     9         // 在构造中使用同一个参数
    10         setThread st = new setThread(s);
    11         getThread gt = new getThread(s);
    12 
    13         Thread t1 = new Thread(st);// 设置数据
    14         Thread t2 = new Thread(gt); // 获取数据
    15 
    16         t2.start();
    17         t1.start();
    18 
    19     }
    20 }

      

  • 相关阅读:
    $.ajax()、$.post()、$.get()
    Json数据格式
    iOS UIButton 调节文字和图片的位置
    block 中使用 weakSelf
    iOS 移除导航栏黑线
    Swift 设置导航栏透明
    Xcode 8 证书管理 Signing for "xxxx" requires a development team.
    iOS 中文登录 中文参数 转码
    ios apple pay 证书配置
    Missing iOS Distribution signing identity for ... Xcode can request one for you.
  • 原文地址:https://www.cnblogs.com/fuck1/p/5432634.html
Copyright © 2020-2023  润新知