zoukankan      html  css  js  c++  java
  • 生产者消费者模式

    单生产和消费模式

    在Java中,负责产生数据的模块的是生产者,负责使用数据的模块是消费者,生产者消费者解决数据的平衡问题,即先有数据才能使用,没有数据时消费者需要等待。

    例如:有一个饭店,它有一个厨师和一个服务员,服务员必须等厨师把菜做好了,通知到服务员才能上菜,然后返回继续等待,厨师代表生产者,服务员代表消费者,两个任务在被消费和生产同时运行。

    public class Text17 {
        public static void main(String[] args) {
            ValueOP valueOP=new ValueOP();
            //测试生产-消费
            ProductThread productThread=new ProductThread(valueOP);
            ConsumerThread consumerThread=new ConsumerThread(valueOP);
    
            productThread.start();
            consumerThread.start();
        }
    }
    //定义线程类模拟生产者
    class  ProductThread extends Thread
    {
        private ValueOP obj;
        public  ProductThread(ValueOP obj)
        {
            this.obj=obj;
        }
    
        @Override
        public void run() {
           while (true)
           {
               try {
                   obj.SetValue();
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }
        }
    }
    class  ConsumerThread extends Thread
    {
        private ValueOP obj;
        public  ConsumerThread(ValueOP obj)
        {
            this.obj=obj;
        }
    
        @Override
        public void run() {
            while (true)
            {
                try {
                    obj.GetValue();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    //SetValue用来设置值,如果不为空就不设置值,如果GetValue为空,就等待不读取,这样前一个设置后一个读取
    class  ValueOP
    {
        public  String value="";
        //修改值方法
        public  void  SetValue() throws InterruptedException {
            synchronized (this)
            {
                //如果不是空字符串就等待
                if(!value.equalsIgnoreCase(""))
                {
                    this.wait();
                }
                //如果是空串就设置value值
                String value=System.currentTimeMillis()+"-"+System.nanoTime();
                System.out.println("set设置的是"+value);
                this.value=value;
                this.notify();
            }
        }
        //读取字段
        public  void GetValue() throws InterruptedException {
            synchronized (this)
            {
                //如果是空字符串就等待
                if(value.equalsIgnoreCase(""))
                {
                    this.wait();
                }
                //不是空串就读取,并赋值为空
                System.out.println("get的值是:"+value);
                this.value="";
                this.notify();
            }
        }
    }
    

    image-20210317233223367

    这样生产与消费交替运行

    多生产和消费模式

    一个饭店有多个厨师和服务员,当厨师们做菜过快了,导致服务员上菜速度跟不上,导致菜堆积在窗口,这时候要让厨师停止生产,等待服务员把菜上完,再继续做菜。如果服务员们上菜速度太快了,厨师没有做完,多名服务员又想上菜,这时候要等待厨师做菜。

    public class Text17 {
        public static void main(String[] args) {
            ValueOP valueOP=new ValueOP();
            //测试生产-消费
            ProductThread productThread=new ProductThread(valueOP);
            ProductThread productThread2=new ProductThread(valueOP);
            ConsumerThread consumerThread=new ConsumerThread(valueOP);
            ConsumerThread consumerThread2=new ConsumerThread(valueOP);
            productThread.start();
            productThread2.start();;
            consumerThread.start();
            consumerThread2.start();
        }
    }
    //定义线程类模拟生产者
    class  ProductThread extends Thread
    {
        private ValueOP obj;
        public  ProductThread(ValueOP obj)
        {
            this.obj=obj;
        }
    
        @Override
        public void run() {
           while (true)
           {
               try {
                   obj.SetValue();
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }
        }
    }
    class  ConsumerThread extends Thread
    {
        private ValueOP obj;
        public  ConsumerThread(ValueOP obj)
        {
            this.obj=obj;
        }
    
        @Override
        public void run() {
            while (true)
            {
                try {
                    obj.GetValue();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    //SetValue用来设置值,如果不为空就不设置值,如果GetValue为空,就等待不读取,这样前一个设置后一个读取
    class  ValueOP
    {
        public  String value="";
        //修改值方法
        public  void  SetValue() throws InterruptedException {
            synchronized (this)
            {
                //如果不是空字符串就等待
                while (!value.equalsIgnoreCase(""))
                {
                    this.wait();
                }
                //如果是空串就设置value值
                String value=System.currentTimeMillis()+"-"+System.nanoTime();
                System.out.println("set设置的是"+value);
                this.value=value;
                this.notifyAll();
            }
        }
        //读取字段
        public  void GetValue() throws InterruptedException {
            synchronized (this)
            {
                //如果是空字符串就等待
                while (value.equalsIgnoreCase(""))
                {
                    this.wait();
                }
                //不是空串就读取,并赋值为空
                System.out.println("get的值是:"+value);
                this.value="";
                this.notifyAll();
            }
    
        }
    }
    

    image-20210319001051071

    在多生产消费的环境notify不能保证是唤醒消费者,如果生产者唤醒生产者就会出现假死情况。

    通过管道实现线程通信

    在java.io包中的pipeStream管道流用于在线程之间传送数据,一个线程发送数据到输出管道,另一个线程从输入管道读取数据,相关的类包括:pidedInputStream和pipedoutStream,pipedReader和pepedWriter

    import java.awt.print.PrinterIOException;
    import java.io.IOException;
    import java.io.PipedInputStream;
    import java.io.PipedOutputStream;
    
    public class TextWrite {
        public static void main(String[] args) throws IOException {
            PipedInputStream inputStream=new PipedInputStream();
            PipedOutputStream outputStream=new PipedOutputStream();
            inputStream.connect(outputStream);
    
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        WriteData(outputStream);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
    
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        ReadData(inputStream);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
        //定义方法向管道流中写入数据
    public  static  void  WriteData(PipedOutputStream outputStream) throws IOException {
            for (int i = 0; i <100 ; i++) {
                String data=""+i;
                outputStream.write(data.getBytes());//把字节数组写入到输出管道中
            }
            outputStream.close();
    }
    //从管道流中读取数据
        public  static  void  ReadData(PipedInputStream inputStream) throws IOException {
            byte[] bytes=new byte[1024];
            int len=inputStream.read(bytes);//返回读到的字节数,没有读到返回-1
            while (len != -1) {
                System.out.println(new String(bytes, 0, len));
                len=inputStream.read(bytes);//继续从管道读取数据
            }
            inputStream.close();
        }
    }
    
    

    image-20210319003236751

  • 相关阅读:
    logging模块、sys模块、shelve模块
    re模块、hashlib模块
    包、常用模块
    模块
    迭代器、生成器、递归、二分法
    函数对象、函数嵌套、名称空间与作用域、闭包函数、装饰器
    函数
    文件处理
    字符编码
    Djiango导读
  • 原文地址:https://www.cnblogs.com/cg-ww/p/14579866.html
Copyright © 2011-2022 走看看