熊吃蜂蜜问题:
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);
}
}
}
}