去過機場的人應該都會看到放行李的傳送帶,工作人員將託運的行李不停的放入傳送帶,乘客下飛機之後會不停的拿走行李。
這個例子和生產者/消費者設計模式相似。
這種設計模式需要滿足以下三點要求:
(1)生產者生產資料到緩衝區中,消費者從緩衝區中取資料。
(2)如果緩衝區已經滿了,則生產者執行緒阻塞;
(3)如果緩衝區為空,那麼消費者執行緒阻塞。
編寫之前分析:
(1)定義乙個快取佇列,選擇乙個集合當做快取,給予快取上限,快取佇列只有兩種行為(生產資料和消費資料);
(2)定義乙個生產者執行緒,呼叫快取佇列中的生產行為;
(3)定義乙個消費者執行緒,呼叫快取佇列中的消費行為;
開始編寫**:
定義乙個快取佇列
/**
* 公共快取佇列
* 只做兩件事:(1)生產;(2)消費
*/public class publicqueue catch (interruptedexception e)
}else
linkedhashmap.put(putindex, msg);
system.out.println("生產乙個產品,當前商品角標為:"+putindex+"===文字為:"+msg+"===快取長度為:"+linkedhashmap.size());
putindex = (putindex + 1 >= maxcount) ? (putindex + 1) % maxcount : putindex + 1;
}public synchronized t remove() catch (interruptedexception e)
}else
iterator it = linkedhashmap.entryset().iterator();
t t = null;
if(it.hasnext())
return t;
}}
定義乙個生產者執行緒
/**
* 生產者執行緒
*/public class producerthread extends thread
@override
public void run()
}}
定義乙個消費者
/**
* 消費者執行緒
*/public class consumerthread extends thread
@override
public void run()
}}
啟動:
public class producerconsumertest
}
**分析:
(1)生產者/消費者設計模式顧名思義就是兩個互斥執行緒,乙個負責生產,乙個負責消費,兩者是執行緒不安全的;
(2)這裡選擇使用linkedhashmap作為快取佇列,linkedhashmap是乙個雙向鍊錶,用來處理執行緒不安全的資料,可以保證取出第乙個資料,it.next()就是取出第乙個資料。(linkedhashmap可以保證遍歷的順序)
(3)為了保證互斥執行緒的安全性,需要做對應的處理,以上**使用了synchronized 、wait()、notifyall()來保證。
那麼本例中保證執行緒安全還有什麼方案呢?
(1)lock和condition的await、signalall
/**
* 公共快取佇列
* 只做兩件事:(1)生產;(2)消費
*/public class publicqueue
private linkedhashmaplinkedhashmap = new linkedhashmap<>();//緩衝區
public void add(t msg)
linkedhashmap.put(putindex, msg);
system.out.println("生產乙個產品,當前商品角標為:"+putindex+"===文字為:"+msg+"===快取長度為:"+linkedhashmap.size());
putindex = (putindex + 1 >= maxcount) ? (putindex + 1) % maxcount : putindex + 1;
removecondition.signalall();//喚醒所有執行緒
} catch (interruptedexception e) finally
}public t remove()
iterator it = linkedhashmap.entryset().iterator();
if(it.hasnext())
addcondition.signalall();//喚醒所有執行緒
} catch (interruptedexception e) finally
return t;
}}
(2)利用阻塞佇列blockingqueue (最簡單的)
/**
* 公共快取佇列
* 只做兩件事:(1)生產;(2)消費
*/public class publicqueue catch (interruptedexception e)
system.out.println("生產乙個產品,當前商品角標為:"+"===文字為:"+msg);
}public t remove() catch (interruptedexception e)
system.out.println("消費乙個產品,當前商品角標為:"+"===文字為:"+t);
return t;
}}
總結:
有關快取佇列的處理有三種方法:
(1)雙向鍊錶linkedhashmap和synchronized結合;
(2)雙向鍊錶linkedhashmap和lock結合;
(3)直接使用阻塞佇列blockingqueue。
生產者消費者 生產者與消費者模式
一 什麼是生產者與消費者模式 其實生產者與消費者模式就是乙個多執行緒併發協作的模式,在這個模式中呢,一部分執行緒被用於去生產資料,另一部分執行緒去處理資料,於是便有了形象的生產者與消費者了。而為了更好的優化生產者與消費者的關係,便設立乙個緩衝區,也就相當於乙個資料倉儲,當生產者生產資料時鎖住倉庫,不...
生產者消費者
using system using system.collections.generic using system.threading namespace gmservice foreach thread thread in producers q.exit console.read public...
生產者消費者
執行緒通訊 乙個執行緒完成了自己的任務時,要通知另外乙個執行緒去完成另外乙個任務.wait 等待 如果執行緒執行了wait方法,那麼該執行緒會進入等待的狀態,等待狀態下的執行緒必須要被其他執行緒呼叫notify方法才能喚醒。notify 喚醒 喚醒執行緒池等待執行緒其中的乙個。notifyall 喚...