Java多線程之消費(fèi)者生產(chǎn)者模式
作者:shijinupc 
  這個實例應(yīng)該是學(xué)習(xí)線程的一個經(jīng)典例子,生產(chǎn)者和消費(fèi)者模式。代碼寫的很好,詳細(xì)請看內(nèi)容。
 
- /*@author shijin
 - * 生產(chǎn)者與消費(fèi)者模型中,要保證以下幾點(diǎn):
 - * 1 同一時間內(nèi)只能有一個生產(chǎn)者生產(chǎn) 生產(chǎn)方法加鎖sychronized
 - * 2 同一時間內(nèi)只能有一個消費(fèi)者消費(fèi) 消費(fèi)方法加鎖sychronized
 - * 3 生產(chǎn)者生產(chǎn)的同時消費(fèi)者不能消費(fèi) 生產(chǎn)方法加鎖sychronized
 - * 4 消費(fèi)者消費(fèi)的同時生產(chǎn)者不能生產(chǎn) 消費(fèi)方法加鎖sychronized
 - * 5 共享空間空時消費(fèi)者不能繼續(xù)消費(fèi) 消費(fèi)前循環(huán)判斷是否為空,空的話將該線程wait,釋放鎖允許其他同步方法執(zhí)行
 - * 6 共享空間滿時生產(chǎn)者不能繼續(xù)生產(chǎn) 生產(chǎn)前循環(huán)判斷是否為滿,滿的話將該線程wait,釋放鎖允許其他同步方法執(zhí)行
 - */
 - //主類
 - 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);
 - tp.start();
 - tc.start();
 - }
 - }
 - //
 - class Mantou
 - {
 - private int id;
 - Mantou(int id){
 - this.id = id;
 - }
 - public String toString(){
 - return "Mantou :" + id;
 - }
 - }
 - //共享??臻g
 - class StackBasket
 - {
 - Mantou sm[] = new Mantou[6];
 - int index = 0;
 - /**
 - * show 生產(chǎn)方法.
 - * show 該方法為同步方法,持有方法鎖;
 - * show 首先循環(huán)判斷滿否,滿的話使該線程等待,釋放同步方法鎖,允許消費(fèi);
 - * show 當(dāng)不滿時首先喚醒正在等待的消費(fèi)方法,但是也只能讓其進(jìn)入就緒狀態(tài),
 - * show 等生產(chǎn)結(jié)束釋放同步方法鎖后消費(fèi)才能持有該鎖進(jìn)行消費(fèi)
 - * @param m 元素
 - * @return 沒有返回值
 - */
 - public synchronized void push(Mantou m){
 - try{
 - while(index == sm.length){
 - System.out.println("!!!!!!!!!生產(chǎn)滿了!!!!!!!!!");
 - this.wait();
 - }
 - this.notify();
 - }catch(InterruptedException e){
 - e.printStackTrace();
 - }catch(IllegalMonitorStateException e){
 - e.printStackTrace();
 - }
 - sm[index] = m;
 - index++;
 - System.out.println("生產(chǎn)了:" + m + " 共" + index + "個饅頭");
 - }
 - /**
 - * show 消費(fèi)方法
 - * show 該方法為同步方法,持有方法鎖
 - * show 首先循環(huán)判斷空否,空的話使該線程等待,釋放同步方法鎖,允許生產(chǎn);
 - * show 當(dāng)不空時首先喚醒正在等待的生產(chǎn)方法,但是也只能讓其進(jìn)入就緒狀態(tài)
 - * show 等消費(fèi)結(jié)束釋放同步方法鎖后生產(chǎn)才能持有該鎖進(jìn)行生產(chǎn)
 - * @param b true 表示顯示,false 表示隱藏
 - * @return 沒有返回值
 - */
 - public synchronized Mantou pop(){
 - try{
 - while(index == 0){
 - System.out.println("!!!!!!!!!消費(fèi)光了!!!!!!!!!");
 - this.wait();
 - }
 - this.notify();
 - }catch(InterruptedException e){
 - e.printStackTrace();
 - }catch(IllegalMonitorStateException e){
 - e.printStackTrace();
 - }
 - index--;
 - System.out.println("消費(fèi)了:---------" + sm[index] + " 共" + index + "個饅頭");
 - return sm[index];
 - }
 - }
 - class Producer implements Runnable
 - {
 - StackBasket ss = new StackBasket();
 - Producer(StackBasket ss){
 - this.ss = ss;
 - }
 - /**
 - * show 生產(chǎn)進(jìn)程.
 - */
 - public void run(){
 - for(int i = 0;i < 20;i++){
 - Mantou m = new Mantou(i);
 - ss.push(m);
 - // System.out.println("生產(chǎn)了:" + m + " 共" + ss.index + "個饅頭");
 - // 在上面一行進(jìn)行測試是不妥的,對index的訪問應(yīng)該在原子操作里,因為可能在push之后此輸出之前又消費(fèi)了,會產(chǎn)生輸出混亂
 - try{
 - Thread.sleep((int)(Math.random()*500));
 - }catch(InterruptedException e){
 - e.printStackTrace();
 - }
 - }
 - }
 - }
 - class Consumer implements Runnable
 - {
 - StackBasket ss = new StackBasket();
 - Consumer(StackBasket ss){
 - this.ss = ss;
 - }
 - /**
 - * show 消費(fèi)進(jìn)程.
 - */
 - public void run(){
 - for(int i = 0;i < 20;i++){
 - Mantou m = ss.pop();
 - // System.out.println("消費(fèi)了:---------" + m + " 共" + ss.index + "個饅頭");
 - // 同上 在上面一行進(jìn)行測試也是不妥的,對index的訪問應(yīng)該在原子操作里,因為可能在pop之后此輸出之前又生產(chǎn)了,會產(chǎn)生輸出混亂
 - try{
 - Thread.sleep((int)(Math.random()*1000));
 - }catch(InterruptedException e){
 - e.printStackTrace();
 - }
 - }
 - }
 - }
 
原文鏈接:http://blog.csdn.net/shijinupc/article/details/7250407
【編輯推薦】
責(zé)任編輯:林師授 
                    來源:
                    shijinupc的博客
 














 
 
 








 
 
 
 