zoukankan      html  css  js  c++  java
  • 生产者与消费者(综合案例)

    基础模型:

      生产者和消费者是一道最为经典的供求案例,而想这供求案例:provider、consumer 在以后进行各种分布式结构开发之后都会被大量采用

      现在假设说目的:生产者负责生产一个完整的数据之后,消费者就要把这些数据取走。于是现在假设生产如下的数据:

        title=老李 note=是个好人

        title=名族败类 note=老方B

    范例:编写程序的基础模型

     1 package cn.Tony.demo;
     2 public  class TestDemo {
     3     public static void main(String[] args) throws Exception {
     4         Data data=new Data();
     5         new Thread(new DataProvider(data)).start();
     6         new Thread(new DataConsumer(data)).start();
     7     }
     8 }
     9 class DataProvider implements Runnable{
    10     private Data data;
    11     public DataProvider(Data data) {
    12         this.data=data;
    13     }
    14     @Override
    15     public void run() {
    16         for(int x=0;x<50;x++) {
    17             if(x%2==0) {
    18                 this.data.setTitle("老李");
    19                 try {
    20                     Thread.sleep(1000);
    21                 } catch (InterruptedException e) {
    22                     e.printStackTrace();
    23                 }
    24                 this.data.setNote("是个好人");
    25             }else {
    26                 this.data.setTitle("民族败类");
    27                 try {
    28                     Thread.sleep(1000);
    29                 } catch (InterruptedException e) {
    30                     e.printStackTrace();
    31                 }
    32                 this.data.setNote("老方b");
    33             }
    34         }
    35     }
    36 }
    37 class DataConsumer implements Runnable{
    38     private Data data;
    39     public DataConsumer(Data data) {
    40         this.data=data;
    41     }
    42     @Override
    43     public void run() {
    44         for(int x=0;x<50;x++) {
    45             try {
    46                 Thread.sleep(1000);
    47             } catch (InterruptedException e) {
    48                 // TODO Auto-generated catch block
    49                 e.printStackTrace();
    50             }
    51             System.out.println(this.data.getTitle()+"="+this.data.getNote());
    52         }
    53     } 
    54 }
    55 class Data{//负责数据保存
    56     private String title;
    57     private String note;
    58     public void setNote(String note) {
    59         this.note=note;
    60     }
    61     public String getNote() {
    62         return this.note;
    63     }
    64     public void setTitle(String title) {
    65         this.title=title;
    66     }
    67     public String getTitle() {
    68         return this.title;
    69     }
    70 }
    71  

      这个时候就已经可以发现程序出现两类问题:

        数据不完整,明明是好人,结果成败类

        数据的重复操作问题(重复设置,或重复取出)

    解决重复问题

      如果要想解决同步问题,那么可以立刻想到使用synchronized关键字来定义同步的操作方法,所以代码修改如下:

     1 package cn.Tony.demo;
     2 public  class TestDemo {
     3     public static void main(String[] args) throws Exception {
     4         Data data=new Data();
     5         new Thread(new DataProvider(data)).start();
     6         new Thread(new DataConsumer(data)).start();
     7     }
     8 }
     9 class DataProvider implements Runnable{
    10     private Data data;
    11     public DataProvider(Data data) {
    12         this.data=data;
    13     }
    14     @Override
    15     public void run() {
    16         for(int x=0;x<50;x++) {
    17             if(x%2==0) {
    18                 this.data.set("老李","老李是个好人");
    19                 
    20             }else {
    21                 this.data.set("民族败类","老放b");
    22             }
    23         }
    24     }
    25 }
    26 class DataConsumer implements Runnable{
    27     private Data data;
    28     public DataConsumer(Data data) {
    29         this.data=data;
    30     }
    31     @Override
    32     public void run() {
    33         for(int x=0;x<50;x++) {
    34             this.data.get();
    35         }
    36     } 
    37 }
    38 class Data{//负责数据保存
    39     private String title;
    40     private String note;
    41     public synchronized void get() {
    42         try {
    43             Thread.sleep(50);
    44         } catch (InterruptedException e) {
    45             // TODO Auto-generated catch block
    46             e.printStackTrace();
    47         }
    48         System.out.println(this.title+"="+this.note);
    49     }
    50     public synchronized void set(String title,String note) {
    51         this.title=title;
    52         try {
    53             Thread.sleep(100);
    54         } catch (InterruptedException e) {
    55             // TODO Auto-generated catch block
    56             e.printStackTrace();
    57         }
    58         this.note=note;
    59     }
    60 }
    61  

      于是现在发现,整个的程序里面数据的同步问题得到了很好的,但是重复操作的问题更加严重了,

    解决数据的重复操作问题:

      如果想要解决重复问题,就要添加唤醒和等待机制,如果想使用这一个功能,那么就要参考Object类中的方法。

      等待 死等:public final void wait()throws InterruptedException

      唤醒第一个等待线程:public final void notify()

      唤醒全部等待线程,那 个优先级高,谁有可能先执行:public final void notifyAll()

    范例:通过等待和唤醒机制解决重复操作问题

     1 package cn.Tony.demo;
     2 public  class TestDemo {
     3     public static void main(String[] args) throws Exception {
     4         Data data=new Data();
     5         new Thread(new DataProvider(data)).start();
     6         new Thread(new DataConsumer(data)).start();
     7     }
     8 }
     9 class DataProvider implements Runnable{
    10     private Data data;
    11     public DataProvider(Data data) {
    12         this.data=data;
    13     }
    14     @Override
    15     public void run() {
    16         for(int x=0;x<50;x++) {
    17             if(x%2==0) {
    18                 this.data.set("老李","老李是个好人");
    19                 
    20             }else {
    21                 this.data.set("民族败类","老放b");
    22             }
    23         }
    24     }
    25 }
    26 class DataConsumer implements Runnable{
    27     private Data data;
    28     public DataConsumer(Data data) {
    29         this.data=data;
    30     }
    31     @Override
    32     public void run() {
    33         for(int x=0;x<50;x++) {
    34             this.data.get();
    35         }
    36     } 
    37 }
    38 class Data{//负责数据保存
    39     private String title;
    40     private String note;
    41     //flag=true 表示允许生产不允许消费者取走
    42     //flag=false 表示生产完毕允许消费者取走不允许生产
    43     private boolean flag=false;
    44     public synchronized void get() {
    45         if(this.flag==false) {//已经生产了,所以不允许重复生产
    46             try {
    47                 super.wait();
    48             } catch (InterruptedException e1) {
    49                 // TODO Auto-generated catch block
    50                 e1.printStackTrace();
    51             }//等待执行 
    52         }
    53         try {
    54             Thread.sleep(50);
    55         } catch (InterruptedException e) {
    56             // TODO Auto-generated catch block
    57             e.printStackTrace();
    58         }
    59         System.out.println(this.title+"="+this.note);
    60         this.flag=false;//表示生产过了。不允许再生产了
    61         super.notify();//唤醒等待线程
    62     }
    63     public synchronized void set(String title,String note) {
    64         if(this.flag==true) {//现在不允许取走
    65             try {
    66                 super.wait();
    67             } catch (InterruptedException e) {
    68                 // TODO Auto-generated catch block
    69                 e.printStackTrace();
    70             }
    71         }
    72         this.title=title;
    73         try {
    74             Thread.sleep(100);
    75         } catch (InterruptedException e) {
    76             // TODO Auto-generated catch block
    77             e.printStackTrace();
    78         }
    79         this.note=note;
    80         this.flag=true;//继续生产
    81         super.notify();
    82     }
    83 }
    84  

    面试题:请解释sleep()与wait()的区别

      sleep()是Thread类的方法到了一定的时间后该休眠自动唤醒

      wait()是Object类中的方法,要想唤醒必须使用notify(),notifyAll()

  • 相关阅读:
    接口缓存--把接口放在redis数据库中,减少访问量
    使用vue和drf后台进行登录页面和注册页面(本文大概的疏通一下前后台是怎么交互的)
    vue导入css,js和放置html代码
    存储过程
    触发器
    视图
    pymysql模块使用
    权限管理
    多表数据查询
    单表数据查询
  • 原文地址:https://www.cnblogs.com/Tony98/p/10491952.html
Copyright © 2011-2022 走看看