【代码练习6】利用多线程生产消费问题实现熊吃蜂蜜问题

来源:互联网 发布:英国知名网络品牌 编辑:程序博客网 时间:2024/05/01 08:17

熊吃蜂蜜问题:
2只熊,100只蜜蜂,
蜜蜂每次生成的蜂蜜量为1,罐子的容量是50,当罐子的蜂蜜量达到20时,熊就吃光。
罐子使用单例设计模式实现。

import java.util.LinkedList;import java.util.List;/*熊吃蜂蜜问题:        2只熊,100只蜜蜂,        蜜蜂每次生成的蜂蜜量为1,罐子的容量是50,当罐子的蜂蜜量达到20时,熊就吃光。        罐子使用单例设计模式实现。 */public class BearEatHoney {    public static void main(String[] args) {        Pot pot = new Pot();        Bear b1 = new Bear("熊大",pot);        Bear b2 = new Bear("熊二",pot);        b1.start();        b2.start();        //开启100只蜜蜂的线程        for(int i = 1;i <= 100;i++){            new Bee(i + "号蜜蜂",pot).start();        }    }    //罐子类:单例设计模式(懒汉模式)    static class Pot {        //拥有一个类类型的成员变量。        private Pot pot = null;        //罐子集合        private List<Integer> list = null;        //罐子的容积        private int Max = 50;        //私有化构造器        private Pot(){            list = new LinkedList<Integer>();        }        //通过相应的公有方法获得对象        public Pot getPot(){            if(pot!= null){                return pot;            }            synchronized (this){                if(pot == null){                    pot = new Pot();                }                return pot;            }        }        //构造罐子添加蜂蜜的方法,为保证线程安全,采用synchronized同步代码块对add方法上锁        public synchronized void add(int n,String beeName) {                while (list.size() == Max) {                    try {                        this.wait();//当罐子灌满时,调用该方法的蜜蜂线程进入等待列表                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }                list.add(n);            /*如果将打印方法放在蜜蜂线程里,由于在多线程的状态下,在控制台打印的顺序并不能真正反映处理器处理的顺序,            *为了更好的查看运行结果,所以我暂且选择放在了同步代码块里。            *但其实在实际应用时,为提高程序运行速度,应该尽量减少同步代码块里的执行动作*/                System.out.println(beeName + "加了一滴,罐子里有" + list.size() + "滴蜂蜜");                this.notifyAll();        }        //构造罐子的移除方法,同样为了保证线程安全,采用synchronized同步代码块对clean方法上锁        public synchronized void clean(String bearName) {                while (list.size() < 20) {                    try {                        this.wait();//当罐子里蜂蜜的量小于20时,调用该方法的线程进入等待列表                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }                list.clear();                this.notifyAll();            System.out.println("\r\n" + "Y(● ̄(エ) ̄●)Y " + bearName + "把蜂蜜吃光了。。。。" + "\r\n");        }    }    //蜂蜜线程    static class Bee extends Thread{        private Pot pot;        private String beeName;        public Bee() {}        public Bee(String beeName,Pot pot){            this.beeName = beeName;            this.pot = pot;        }        public void run() {            for (;;){                try {                    pot.add(1,beeName);                     /*                *蜜蜂线程太多,总有更大的概率抢到罐子,所以同等条件下熊多数时候是在罐子灌满时才能吃到蜂蜜,                *为了让熊尽可能在多种情况下都能吃到,我们就让蜜蜂每次放完蜂蜜后时候睡一下                */                    Thread.sleep(10);                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }    }    //熊线程    static class Bear extends Thread{        private Pot pot;        private String bearName;        public Bear(){}        public Bear(String bearName,Pot pot){            this.bearName = bearName;            this.pot = pot;        }        public void run(){            for (;;){                    pot.clean(bearName);            }        }    }}
原创粉丝点击