zoukankan      html  css  js  c++  java
  • 生产者消费者java实现

    生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区线程——即所谓的生产者消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。

    我们在实现实时显示日志的时候,想到了用这个方法:当远程服务器执行命令时,先把日志写入一个缓存中,然后客户端一直读取缓存中的数据,这样就能实现实时读取。当然我们先验证一下生产者消费者多线程同步问题。

    一,  定义一个缓存,并定义相应的读写互斥操作。代码如下所示:

     //文件Buffer.java

    package thread;

     

    import java.sql.Date;

    import java.text.SimpleDateFormat;

     

    // 生产者与消费者共享的缓冲区,必须实现读、写的同步

    public class Buffer {

        private String contents;

        private boolean available = false;

        public synchronized String get() {

            while (! available) {

                try {

                    this.wait();

                   

                } catch (InterruptedException exc) {}

            }

            String value = contents;

            // 消费者取出内容,改变存取控制available

            available = false;

            //System.out.println("取出" + contents);

            this.notifyAll();

            return value;

        }

        public synchronized void put(String value) {

            while (available) {

                try {

                    this.wait();

                } catch (InterruptedException exc) {}

            }

            contents = value;

            available = true;

            //System.out.println("放入" + contents);

           

            this.notifyAll();

        }

    }

    通过available变量进行互斥控制,当然具体执行过程我们就不详细讲述,这是一个经典的问题,到处都有讲解。

    二,  生产者,往缓存中放入数据。

    生产者,不断地往缓存中放入数据,放入前先检测缓存中是否有数据,如果有,则等待数据被读出后再放入。示例代码如下:

    //producer.java

    package thread;

    // 生产者线程

     

    public class Producer extends Thread {

             private Buffer buffer;

             private int number;

             private String mes="good";

             public Producer(Buffer buffer, int number) {

                       this.buffer = buffer;

                       this.number = number;

             }

             public void setString(String message)

             {

                       this.mes=message;

             }

             @SuppressWarnings("deprecation")

             public void run() {

                       for (int i = 0;;) {

                                buffer.put(this.mes+i);

                                if(i==10)

                                {

                                         break;

                                }

                                System.out.println("生产者#" + number + "生产: " + i++);

                                try {

                                         Thread.sleep((int) (Math.random() * 100));

                                } catch (InterruptedException exc) {}

                       }

             }

    此段代码里加了一个条件,当生产者生产了10个数据后,但中断,不再生产。

    三,  消费者,读出缓存中的数据

    消费者,不断地从缓存中读取数据,在读取数据之前先检测缓存中是否有数据,如果没有则等待;如果有则读取。示例代码如下所示:

    //consumer.java

    package thread;

    // 消费者线程

    public class Consumer extends Thread {

             private Buffer buffer;

             private int number;

             private  boolean stopflag=true;//设置停止标志

             public Consumer(Buffer buffer, int number) {

                       this.buffer = buffer;

                       this.number = number;

             }

             public void setstop(boolean flag)

             {

                       this.stopflag=flag;

             }

             public void run() {

                       for (;;) {

                                String v = buffer.get();

                                System.out.println("消费者#" + number + "消费:" + v);

                                if(v.contains("10"))

                                {

                                         System.out.println("Can be stop!!!");

                                         this.stop();

                                }

                       }

             }

    }

       当然消费者代码段中也加了限制,当读取的数据中包含“10”,则输入“Can be stop!!!”,并中断线程执行。这样做的目的是,当生产者停止生产数据时,消费者也需要停止读取进程。

    四,  生产者消费者调用程序

    我们上面写了缓存的读取,生产者线程和消费者线程,下面我们就写段程序调试一下:

    import java.sql.Date;

    import java.text.SimpleDateFormat;

     

    // 演示生产者∕消费者问题的主程序

    public class ProducerConsumerProblem {

        public static void main(String[] args) {

            Buffer buffer = new Buffer();

            Producer pro= new Producer(buffer, 100);

            pro.setString("Today is a fine day!");

            pro.start();

            new Consumer(buffer, 300).start();

       

        }

    }

    运行这个程序,则会显示出如下运行结果:

     生产者消费者java实现

      当生产和消费都达到10时,则中断进程执行。

     

                     

     

  • 相关阅读:
    error C4430: 缺少类型说明符
    Fiddler 教程
    make: Nothing to be done for 'first'
    Qt Creator + MinGW 在windows 下的调试GDB停止工作解决
    WIN7成功安装Qt4.8方法,无需VS支持
    深入研究 UCenter API For .NET
    C#在Winform程序中显示QQ在线状态
    VS2010 需要缺少的web组件才能加载该项目
    System.Runtime.InteropServices.COMException: 检索 COM 类工厂中 CLSID 为 {0002E510-0000-0000-C000-000000000046} 的组件时失败,原因是出现以下错误: 80040154
    c#while循环注意continue的地方
  • 原文地址:https://www.cnblogs.com/eagleking0318/p/6520743.html
Copyright © 2011-2022 走看看