/*@author shijin * 生產者與消費者模型中要保證以下幾點* 同一時間內只能有一個生產者生產 生產方法加鎖sychronized * 同一時間內只能有一個消費者消費 消費方法加鎖sychronized * 生產者生產的同時消費者不能消費 生產方法加鎖sychronized * 消費者消費的同時生產者不能生產 消費方法加鎖sychronized * 共享空間空時消費者不能繼續消費 消費前循環判斷是否為空空的話將該線程wait釋放鎖允許其他同步方法執行* 共享空間滿時生產者不能繼續生產 生產前循環判斷是否為滿滿的話將該線程wait釋放鎖允許其他同步方法執行*/
//主類class ProducerConsumer { public static void main(String[] args)
{ StackBasket s = new StackBasket()Producer p = new Producer(s)Consumer c = new Consumer(s)Thread tp = new Thread(p)Thread tc = new Thread(c)tpstart()tcstart()}
// class Mantou { private int id
Mantou(int id){ thisid = id}
public String toString(){ return Mantou + id}
//共享棧空間class StackBasket { Mantou sm[] = new Mantou[]int index =
/** * show 生產方法
* show 該方法為同步方法持有方法鎖* show 首先循環判斷滿否滿的話使該線程等待釋放同步方法鎖允許消費* show 當不滿時首先喚醒正在等待的消費方法但是也只能讓其進入就緒狀態* show 等生產結束釋放同步方法鎖後消費才能持有該鎖進行消費* @param m 元素* @return 沒有返回值*/
public synchronized void push(Mantou m){ try{ while(index == smlength){ Systemoutprintln(!!!!!!!!!生產滿了!!!!!!!!!)thiswait()} thisnotify()}catch(InterruptedException e){ eprintStackTrace()}catch(IllegalMonitorStateException e){ eprintStackTrace()}
sm[index] = mindex++Systemoutprintln(生產了 + m + 共 + index + 個饅頭)}
/** * show 消費方法* show 該方法為同步方法持有方法鎖* show 首先循環判斷空否空的話使該線程等待釋放同步方法鎖允許生產* show 當不空時首先喚醒正在等待的生產方法但是也只能讓其進入就緒狀態* show 等消費結束釋放同步方法鎖後生產才能持有該鎖進行生產* @param b true 表示顯示false 表示隱藏* @return 沒有返回值*/ public synchronized Mantou pop(){ try{ while(index == ){ Systemoutprintln(!!!!!!!!!消費光了!!!!!!!!!)thiswait()} thisnotify()}catch(InterruptedException e){ eprintStackTrace()}catch(IllegalMonitorStateException e){ eprintStackTrace()} index——Systemoutprintln(消費了—— + sm[index] + 共 + index + 個饅頭)return sm[index]}
class Producer implements Runnable { StackBasket ss = new StackBasket()Producer(StackBasket ss){ thisss = ss}
/** * show 生產進程
*/ public void run(){ for(int i = i < i++){ Mantou m = new Mantou(i)sspush(m)// Systemoutprintln(生產了 + m + 共 + ssindex + 個饅頭)// 在上面一行進行測試是不妥的對index的訪問應該在原子操作裡因為可能在push之後此輸出之前又消費了會產生輸出混亂try{ Threadsleep((int)(Mathrandom()*))}catch(InterruptedException e){ eprintStackTrace()}
class Consumer implements Runnable { StackBasket ss = new StackBasket()Consumer(StackBasket ss){ thisss = ss}
/** * show 消費進程
*/ public void run(){ for(int i = i < i++){ Mantou m = sspop()// Systemoutprintln(消費了—— + m + 共 + ssindex + 個饅頭)// 同上 在上面一行進行測試也是不妥的對index的訪問應該在原子操作裡因為可能在pop之後此輸出之前又生產了會產生輸出混亂try{ Threadsleep((int)(Mathrandom()*))}catch(InterruptedException e){ eprintStackTrace()}
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26006.html