執行緒間的協作(2)——生產者與消費者模式
1.何為生產者與消費者
線上程世界裡,生產者就是生產資料的執行緒,消費者就是消費資料的執行緒。
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* @ClassName:Restraurant
* @Description:何為生產者與消費者
* @author:
* @date:2018年5月3日
*/
public class Restraurant {
Meal m=null;
Chef chef=new Chef(this);
WaitPerson wait=new WaitPerson(this);
ExecutorService service=Executors.newCachedThreadPool();
public Restraurant() {
service.execute(chef);
service.execute(wait);
}
public static void main(String[] args) {
new Restraurant();
}
}
/**
* @ClassName:Meal
* @Description:生產者生成的資料
* @author:
* @date:2018年5月3日
*/
class Meal{
private final int orderNum;//食物訂單編號
public Meal(int num){
orderNum=num;
}
public String toString(){
return "Meal"+orderNum;
}
}
/**
* @ClassName:Chef
* @Description:廚師類,及生產者
* @author:
* @date:2018年5月3日
*/
class Chef implements Runnable{
Restraurant r;
int count=0;
public Chef(Restraurant r) {
this.r=r;
}
@Override
public void run() {
try{
while(!Thread.interrupted()){
synchronized (this) {
while(r.m!=null){
System.out.println("廚師等待中");
wait();//等待服務員取餐
}
}
if(count++==10){
System.out.println("今日已售完");
r.service.shutdownNow();
}
System.out.println("訂單完成,服務員取餐");
synchronized (r.wait) {
r.m=new Meal(count);
r.wait.notifyAll();
}
TimeUnit.SECONDS.sleep(1);
}
}catch (InterruptedException e) {
System.out.println("生產者執行緒強制中斷");
}
}
}
/**
* @ClassName:WaitPerson
* @Description:服務員類,即消費者
* @author:
* @date:2018年5月3日
*/
class WaitPerson implements Runnable{
Restraurant r;
public WaitPerson(Restraurant r) {
this.r=r;
}
@Override
public void run() {
try {
while (!Thread.interrupted()) {
synchronized (this) {
while (r.m == null) {
System.out.println("服務員等待中");
wait();// 等待廚師生成食物
}
}
System.out.println("服務員以取餐" + r.m);
synchronized (r.chef) {
r.m = null;
r.chef.notifyAll();
}
}
} catch (InterruptedException e) {
System.out.println("消費者執行緒強制中斷");
}
}
}
2.生產者與消費者模式
1)產生原因:在多執行緒開發 中,如果生產者處理速度很快,而消費者處理速度很慢,那麼生產者就必須等待消費者處理 完,才能繼續生產資料。同樣的道理,如果消費者的處理能力大於生產者,那麼消費者就必須 等待生產者。wait與notify方法以一種非常低階的方式解決了任務互相通知的問題,即每次互動都要進行一次握手,極大影響的效率以及效能,為了解決這種生產消費能力不均衡的問題,便有了生產者和消費者模式。
2)原理:生產者和消費者模式是通過一個容器(比如同步阻塞佇列)來解決生產者和消費者的強耦合問題。生產者和消 費者彼此之間不直接通訊,而是通過阻塞佇列來進行通訊,所以生產者生產完資料之後不用 等待消費者處理,直接扔給阻塞佇列,消費者不找生產者要資料,而是直接從阻塞佇列裡取, 阻塞佇列就相當於一個緩衝區,平衡了生產者和消費者的處理能力。 這個阻塞佇列就是用來給生產者和消費者解耦的。java.util.concurrent.BlockingQueue介面提供了這個佇列,通常使用其實現子類ArrayBlockingQueue,LinkedBlockingQueue。當消費者任務試圖從同步佇列中獲取物件,如果佇列為空時,那麼佇列則會掛起消費者任務,並且當擁有足夠多的元素可用時才會恢復消費者任務。
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
public class UseBlockingQueue {
public static void main(String[] args) throws InterruptedException {
LinkedBlockingQueue<Toast> dry=new LinkedBlockingQueue<Toast>(),
butter=new LinkedBlockingQueue<Toast>(),
jam=new LinkedBlockingQueue<Toast>(),
con=new LinkedBlockingQueue<Toast>();
ExecutorService exec=Executors.newCachedThreadPool();
exec.execute(new MakeToast(dry));//製作初始吐司任務
exec.execute(new Butter(dry,butter));//吐司抹黃油任務
exec.execute(new Jam(butter,jam));//吐司抹果醬任務
exec.execute(new Consumer(jam));//消費者任務,食用吐司
TimeUnit.SECONDS.sleep(5);
exec.shutdownNow();
}
}
class Toast{
private int status;//吐司狀態:0代表製作吐司,1代表抹黃油,2代表向抹了黃油的吐司抹果醬
private final int id;
public Toast(int id1) {
id=id1;
}
public void butter(){
status=1;
};
public void jam(){
status=2;
}
public int getStatus(){
return status;
}
public int getId(){
return id;
}
public String toString(){
return "toast "+id+":"+status;
}
}
/**
* @Description:製作初始吐司
*/
class MakeToast implements Runnable{
private LinkedBlockingQueue<Toast> queue=new LinkedBlockingQueue<Toast>();
private int count=0;
public MakeToast(LinkedBlockingQueue<Toast> q) {
queue=q;
}
@Override
public void run() {
try{
while(!Thread.interrupted()){
Thread.sleep(1000);//製作時間
Toast t=new Toast(count);
System.out.println(t);
queue.put(t);//新增到同步佇列
count++;
}
}catch (InterruptedException e) {
System.out.println("make process interrupted");
}
System.out.println("make process off");
}
}
/**
* @Description:塗抹黃油
*/
class Butter implements Runnable{
private LinkedBlockingQueue<Toast> queue1,queue2;//未加料吐司佇列,抹黃油後吐司佇列
public Butter(LinkedBlockingQueue<Toast> q1,LinkedBlockingQueue<Toast>q2) {
queue1=q1;
queue2=q2;
}
@Override
public void run() {
try{
while(!Thread.interrupted()){
Toast t=queue1.take();//如果佇列中沒有可用元素將會阻塞,直至有可用元素被新增
t.butter();
System.out.println(t);
queue2.put(t);
}
}catch (InterruptedException e) {
System.out.println("butter process interrupted");
}
System.out.println("butter process off");
}
}
/**
* @Description:塗抹果醬
*/
class Jam implements Runnable{
private LinkedBlockingQueue<Toast> queue1,queue2;//抹黃油後吐司佇列,抹果醬吐司佇列
public Jam(LinkedBlockingQueue<Toast> q1,LinkedBlockingQueue<Toast>q2) {
queue1=q1;
queue2=q2;
}
@Override
public void run() {
try{
while(!Thread.interrupted()){
Toast t=queue1.take();//如果佇列中沒有可用元素將會阻塞,直至有可用元素被新增
t.jam();
System.out.println(t);
queue2.put(t);
}
}catch (InterruptedException e) {
System.out.println("jam process interrupted");
}
System.out.println("jam process off");
}
}
/**
* @Description:被食用
*/
class Consumer implements Runnable{
private LinkedBlockingQueue<Toast> finished;//抹黃油後吐司佇列,抹果醬吐司佇列
int count=0;
public Consumer(LinkedBlockingQueue<Toast> q) {
finished=q;
}
@Override
public void run() {
try{
while(!Thread.interrupted()){
Toast t=finished.take();//如果佇列中沒有可用元素將會阻塞,直至有可用元素被新增
if(t.getId()!=count++||t.getStatus()!=2){
System.out.println("過程出現錯誤");
return;
}else{
System.out.println("所有過程正確實現"+"toast "+t.getId()+"被食用");
}
}
}catch (InterruptedException e) {
System.out.println("eat process interrupted");
}
System.out.println("eat process off");
}
}
相關文章
- Java 多執行緒(Java.Thread)------ 執行緒協作(生產者消費者模式)Java執行緒thread模式
- python執行緒通訊與生產者消費者模式Python執行緒模式
- java多執行緒:執行緒間通訊——生產者消費者模型Java執行緒模型
- Java多執行緒——消費者與生產者的關係Java執行緒
- Python-多執行緒及生產者與消費者Python執行緒
- Java多執行緒——生產者消費者示例Java執行緒
- 生產者消費者模式--java多執行緒同步方法的應用模式Java執行緒
- Java 多執行緒基礎(十二)生產者與消費者Java執行緒
- python 多執行緒實現生產者與消費者模型Python執行緒模型
- 九、生產者與消費者模式模式
- python中多執行緒消費者生產者問題Python執行緒
- Java 多執行緒學習(執行緒通訊——消費者和生產者)Java執行緒
- 生產者消費者模式模式
- python多執行緒+生產者和消費者模型+queue使用Python執行緒模型
- 生產消費者模式模式
- python 生產者消費者模式Python模式
- C#多執行緒學習(三) 生產者和消費者C#執行緒
- 多執行緒併發如何高效實現生產者/消費者?執行緒
- 使用Python佇列和多執行緒實現生產者消費者Python佇列執行緒
- 使用wait()與notifyAll()實現生產者與消費者模式AI模式
- Java中的設計模式(二):生產者-消費者模式與觀察者模式Java設計模式
- java學習回顧---生產者與消費者問題以及多執行緒補充Java執行緒
- 生產者與消費者問題
- 併發設計模式---生產者/消費者模式設計模式
- 從一次生產消費者的bug看看執行緒池如何增加執行緒執行緒
- 生產者消費者
- PHP操作Beanstalkd佇列(2)生產者與消費者PHPBean佇列
- java進階(40)--wait與notify(生產者與消費者模式)JavaAI模式
- java編寫生產者/消費者模式的程式。Java模式
- 阻塞佇列和生產者-消費者模式佇列模式
- 生產者與消費者之Android audioAndroid
- linux 生產者與消費者問題Linux
- 程式執行緒對比總結以及對於生產者消費者的場景分析執行緒
- 執行緒同步介紹及 生產者消費者問題舉例 C#版執行緒C#
- 生產者消費者模型模型
- 使用BlockQueue實現生產者和消費者模式BloC模式
- java 執行緒池、多執行緒併發實戰(生產者消費者模型 1 vs 10) 附案例原始碼Java執行緒模型原始碼
- 多執行緒必考的「生產者 - 消費者」模型,看齊姐這篇文章就夠了執行緒模型