熊喫蜂蜜問題:
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);
}
}
}
}