生产者消费者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时,则中断进程执行。

 

                 

 

 

posted @ 2016-01-21 16:37  潜龙9527  阅读(200)  评论(0编辑  收藏  举报