多執行緒解決熊吃蜂蜜問題
阿新 • • 發佈:2019-02-17
一、問題
有n只蜜蜂和一隻飢餓的熊。他們共享一罐蜂蜜。這個罐子最初是空的;它的容量是蜜蜂的一半。熊睡到罐子裡的蜂蜜滿了,然後把所有的蜂蜜都吃了,然後再繼續睡覺。每隻蜜蜂都要反覆地收集一份蜂蜜,並把它放進罐子裡蜜蜂填滿罐子,喚醒了熊。
二、程式碼
public class BearAndHoneybees { //罐子 public static class Pot { private int start = 0; private int Max; private Pot(int n){ Max = n/2; } } //蜜蜂 public static class Bee extends Thread{ private Pot pot; public Bee(Pot pot){ this.pot=pot; } @Override public void run() { for (;;) try { synchronized (pot) { while (pot.start == pot.Max) { try { pot.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } pot.start++; pot.notifyAll(); } Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } } //熊 public static class Bear extends Thread{ private Pot pot; public Bear(Pot pot){ this.pot=pot; } @Override public void run() { for (;;){ synchronized(pot){ while (pot.start < pot.Max) { try { pot.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } pot.start=0; pot.notifyAll(); } } } } public static void main(String[] args) { int n=100; Pot pot=new Pot(n); for (int i = 0; i <n ; i++) { new Bee(pot).start(); } new Bear(pot).start(); } }
三、求其他解法
類似方案一(XX提供)
public class Test { private static final Integer potLength = 10; public static void main(String[] args) { HoneyPot honeyPot = new HoneyPot(potLength); honeyPot.start(); for (int i = 0; i < 10000; i++) { honeyPot.putHoney(new Object()); System.out.println("密封放置蜂蜜,長度:"+honeyPot.getPot().size()); } System.out.println("跑完了,中斷執行緒..."); honeyPot.interrupt(); } } class HoneyPot extends Thread { private List<Object> pot = new ArrayList<>(); private Integer potLength; final ReentrantLock lock; private final Condition notEmpty; private final Condition notFull; HoneyPot(Integer potLength) { this.potLength = potLength; lock = new ReentrantLock(); notEmpty = lock.newCondition(); notFull = lock.newCondition(); } /** * 密封放置蜂蜜 * * @param object 蜂蜜 */ public void putHoney(Object object) { try { lock.lockInterruptibly(); if (pot.size() >= potLength) { notEmpty.signal(); notFull.await(); } pot.add(object); } catch (Exception e) { System.out.println("putHoney異常"); } finally { lock.unlock(); } } @Override public void run() { while (true) { try { lock.lockInterruptibly(); if (pot.size() < potLength) { notEmpty.await(); } else { Iterator<Object> its = pot.iterator(); while (its.hasNext()) { its.next(); if (pot.size() < (potLength / 2)) { break; } its.remove(); } System.out.println("熊吃掉一半蜂蜜,長度:"+pot.size()); notFull.signal(); } } catch (InterruptedException e) { System.out.println("takeHoney異常"); } finally { lock.unlock(); } } } public List<Object> getPot() { return pot; } }
類似方案二
public class HoneyJar { //罐子最大容量 private final int JAR_MAX_VOL = 100; //罐子當前容量 private volatile int jar_cur_vol = 0; //罐子鎖 private ReentrantLock lock = new ReentrantLock(); //罐子條件--滿 private Condition isFull = lock.newCondition(); //罐子條件--空 private Condition isEmpty = lock.newCondition(); //罐子蜂蜜增加 public void honeyIncrease(){ try { lock.lockInterruptibly(); //罐子滿時通知熊吃蜂蜜並且使蜜蜂等待裝蜂蜜 if(jar_cur_vol >= JAR_MAX_VOL){ isFull.signal(); isEmpty.await(); }else{ Thread.sleep(100); jar_cur_vol++; System.out.println(Thread.currentThread().getName() + "號蜜蜂將蜂蜜裝入罐子,當前罐子蜂蜜容量:" + jar_cur_vol); } } catch (InterruptedException e) { e.printStackTrace(); }finally{ lock.unlock(); } } //罐子蜂蜜減少 public void honeyDecrease(){ try { lock.lockInterruptibly(); //罐子空時通知熊等待並且使蜜蜂開始裝蜂蜜 if(jar_cur_vol == 0){ isFull.await(); isEmpty.signalAll(); }else{ System.out.println("熊正在吃蜂蜜...."); Thread.sleep(1000); do{ jar_cur_vol--; }while(jar_cur_vol > 0); System.out.println("熊已經吃光蜂蜜...."); } } catch (InterruptedException e) { e.printStackTrace(); }finally{ lock.unlock(); } } }
public class Bee implements Runnable{
private HoneyJar jar;
public Bee(HoneyJar jar){
this.jar = jar;
}
@Override
public void run() {
//蜜蜂向罐子裝蜂蜜
for(;;){
jar.honeyIncrease();
}
}
}
public class Bear implements Runnable{
private HoneyJar jar;
public Bear(HoneyJar jar){
this.jar = jar;
}
@Override
public void run() {
//熊吃蜂蜜
for(;;){
jar.honeyDecrease();
}
}
}
public class Test {
public static void main(String[] args) {
HoneyJar hj=new HoneyJar();
for (int i = 0; i <10 ; i++) {
new Thread(new Bee(hj),i+"號bee").start();
}
new Thread(new Bear(hj)).start();
}
}
四、參考解法