简单实现生产者消费者问题

来源:互联网 发布:网络蜘蛛 磁力搜索 编辑:程序博客网 时间:2024/06/07 13:23
    生产者消费者问题,是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程--即所谓的“生产者”和“消费者”在实际运行时会发生的问题。。生产者主要的作用是生产一定量的数据放置到缓冲区,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。    该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区空时消耗数据。

话不多说,直接上代码

/** * 馒头对象 * @author Quan * */public class Cake {              private int id;    public Cake(int id) {        this.id = id;    }    @Override    public String toString() {        return " " + id + " Cake";    }}
/** * 容器对象    用来放馒头 * @author Quan * */public class Frame {    private volatile int count = 0;    //设置容器的大小,最大只能装10个馒头    public synchronized void push(Cake cake){      //放入馒头        try {            while(count>10){       //如果大于容器的数量,就进行等待                wait();            }            count ++;            System.out.println("做第" + cake.toString());            notify();                //通知消费者取馒头        } catch (Exception e) {            System.out.println("push error");        }    }    public synchronized void pop(Cake cake){       //取馒头        try {            while(count == 0){      //如果馒头数量为0,就进行等待                wait();            }            count --;            System.out.println("吃第" + cake.toString());            notify();              //通知生产者做馒头        } catch (Exception e) {            System.out.println("pop error");        }    }    public void count(){                System.out.println("当前剩余" + count + "个馒头");    }}

生产者和消费者都要持有一个容器对象,以对容器中的对象也就是馒头数量进行操作

/** * 生产者 * @author Quan * */public class Producer implements Runnable{    private Frame frame;        //持有容器对象    private int total;    public Producer(Frame frame,int i) {        this.frame = frame;        this.total = i;    }    @Override    public void run() {        try {            for (int i = 0; i < total; i++) {             //做10个馒头                Cake cake = new Cake(i);                frame.push(cake);                Thread.sleep(100);                    //每做一个馒头休眠100毫秒            }        } catch (Exception e) {            System.out.println("Producer Error");        }    }}
/** * 消费者 * @author Quan * */public class Consumer implements Runnable{    private Frame frame;    //持有容器对象    private int total;    public Consumer(Frame frame,int i) {        this.frame = frame;        this.total = i;    }    @Override    public void run() {        try {            for(int i = 0; i < total; i++){                Cake cake = new Cake(i);                frame.pop(cake);                Thread.sleep(200);   //每吃一个馒头,休眠200毫秒                frame.count();            }        } catch (Exception e) {            System.out.println("Consumer Error");        }    }}
/** * 生产者消费者测试主函数 * @author Quan * *//** * 生产者消费者测试主函数 * @author Quan * */public class ProductorConsumer {    public static void main(String[] args) throws Exception {        Frame frame = new Frame();        Consumer consumer = new Consumer(frame,5);       //消费6个馒头        Producer producer = new Producer(frame,6);       //生产5个馒头        ExecutorService exes = Executors.newCachedThreadPool();        exes.execute(producer);        exes.execute(consumer);        TimeUnit.SECONDS.sleep(5);        exes.shutdownNow();    }}

运行程序结果:
这里写图片描述

修改生产消费馒头的数量:

/** * 生产者消费者测试主函数 * @author Quan * */public class ProductorConsumer {    public static void main(String[] args) throws Exception {        Frame frame = new Frame();        Consumer consumer = new Consumer(frame,6);       //消费6个馒头        Producer producer = new Producer(frame,5);       //生产5个馒头        ExecutorService exes = Executors.newCachedThreadPool();        exes.execute(producer);        exes.execute(consumer);        TimeUnit.SECONDS.sleep(5);        exes.shutdownNow();    }}

程序运行结果:
这里写图片描述
这里的pop error原因是:在主线程休眠5秒钟后,产生中断信号,消费者在线程在调用pop去取馒头的等待中接到中断信号,退出等待,抛出java.lang.InterruptedException异常,程序退出pop方法,回到消费者的Thread.sleep(200); //每吃一个馒头,休眠200毫秒 位置,依次执,程序正常退出。

0 0
原创粉丝点击