生产者消费者模型

前言

生产者-消费者问题,实际上主要是包含了两类线程,一种是生产者线程用于生产数据,另一种是消费者线程用于消费数据,为了解耦生产者和消费者的关系,通常会采用共享的数据区域,就像是一个仓库,生产者生产数据之后直接放置在共享数据区中,并不需要关心消费者的行为;而消费者只需要从共享数据区中去获取数据,就不再需要关心生产者的行为。但是,这个共享数据区域中应该具备这样的线程间并发协作的功能

一、代码实现

#include <string>
#include <iostream>
#include <cstdlib>
#include <string>
#include <ctime>
#include "TQueue.h"
#include "zthread/Thread.h"
#include "zthread/Mutex.h"
#include "zthread/Guard.h"
#include "zthread/Condition.h"
#include "zthread/ThreadedExecutor.h"
using namespace ZThread;
using namespace std;

class Car{
private:
	int id;
	bool engine, driveTrain, wheels;
public:
	Car(int idn) : id(idn), engine(false), driveTrain(false), wheels(false){}
	Car() : id(-1), engine(false), driveTrain(false), wheels(false){}
	int getid() { return id; }
	void addEngine() { engine = true; }
	bool engineInstalled() { return engine; }
	void addDriveTrain() { driveTrain = true; }
	bool driveTrainInstalled(){ return driveTrain;}
	void addWheels(){ wheels = true; }
	bool wheelsInstalled(){ return wheels;}
	friend ostream& operator<<(ostream& os, const Car& c){
		return os << "Car" << c.id << " [ " << " engine: " << c.engine << "driveTrain: " << c.driveTrain
			<< " wheels: " << c.wheels << " ] ";
	}
};
typedef CountedPtr<TQueue<Car>> CarQueue;
class ChassisBuilder : public Runnable{
private:
	CarQueue carQueue;
	int counter;
public:
	ChassisBuilder(CarQueue& cq) : carQueue(cq), counter(0){}
	void run(){
		try{
			while(!Thread::interrupted()){
				Thread::sleep(1000);
				Car c(counter++);/*Make chassis*/
				cout << c << endl;/*Insert into queue*/
				carQueue->put(c);
			}
		}catch(Interrupted_Exception&) {}
		cout << "ChassisBuilder off" << endl;
	}
};
class Cradle{
private:
	Car c; /*Holds current car being worked on*/
	bool occupied;
	Mutex workLock, readyLock;
	Condition workCondition, readyCondition;
	bool engineBotHired, wheelBotHired, driveTrainBotHired;
public:
	Cradle() : workCondition(workLock), readyCondition(readyLock){
		occupied = false;
		engineBotHired = true;
		wheelBotHired = true;
		driveTrainBotHired = true;
	}
	void InsertCar(Car chassis){
		c = chassis;
		occupied = true;
	}
	Car getCar(){/*Can only extract car once*/
		if(!occupied){
			cerr << "No Car in Cradle for getCar()" << endl;
			return Car();
		}
		occupied = false;
		return c;
	}
	Car* operator->(){ return &c; }
	void offerEngineBotServices(){/*Allow robots to offer services to this Cradle*/
		Guard<Mutex> g(workLock);
		while(engineBotHired)
			workCondition.wait();
		engineBotHired = true;
	}
	void offerWheelBotServices(){
		Guard<Mutex> g(workLock);
		while(wheelBotHired)
			workCondition.wait();
		wheelBotHired = true;
	}
	void offerDriveTrainBotServices(){
		Guard<Mutex> g(workLock);
		while(driveTrainBotHired)
			workCondition.wait();
		driveTrainBotHired = true;
	}
	void startWork(){/* Tell waiting robots that work is ready*/
		Guard<Mutex>  g(workLock);
		engineBotHired = false;
		wheelBotHired = false;
		driveTrainBotHired = false;
		workCondition.broadcast();
	}
	void taskFinished(){/*Each robot reports when their job is done*/
		Guard<Mutex> g(readyLock);
		readyCondition.signal();
	}
	void waitUntilWorkFinished(){
		Guard<Mutex> g(readyLock);
		while(!(c.engineInstalled() && c.driveTrainInstalled() && c.wheelsInstalled()))
			readyCondition.wait();
	}
};
typedef CountedPtr<Cradle> CradlePtr;
class Director : public Runnable{
private:
	CarQueue chassisQueue, finishingQueue;
	CradlePtr cradle;
public:
	Director(CarQueue& cq, CarQueue& fq, CradlePtr cr) : chassisQueue(cq), finishingQueue(fq), cradle(cr){}
	void run(){
		try{
			while(!Thread::interrupted()){
				cradle->InsertCar(chassisQueue->get());/*Blocks until chassis is available*/
				cradle->startWork();/*Notify robots car is ready for work*/
				cradle->waitUntilWorkFinished();/*Wait until  work completes*/
				finishingQueue->put(cradle->getCar());/*Put car into queue for future work*/
			}
			}catch(Interrupted_Exception&) {}
			cout << " Director off" << endl;
	}
};
class EngineRobot : public Runnable{
private:
	CradlePtr cradle;
public:
	EngineRobot(CradlePtr cr) : cradle(cr){}
	void run(){
		try{
			while(!Thread::interrupted()){
				cradle->offerEngineBotServices();/*Blocks until job is offered/accepted*/
				cout << "Installing engine" << endl;
				(*cradle)->addEngine();
				cradle->taskFinished();
			}
		}catch(Interrupted_Exception&){}
		cout << "EngineRobot off" << endl;
	}
};
class DriveTrainRobot : public Runnable{
private:
	CradlePtr cradle;
public:
	DriveTrainRobot(CradlePtr cr) : cradle(cr){}
	void run(){
		try{
			while(!Thread::interrupted()){
				cradle->offerDriveTrainBotServices();/*Blocks until job is offered/accepted*/
				cout << "Installing DriveTrain" << endl;
				(*cradle)->addDriveTrain();
				cradle->taskFinished();
			}
		}catch(Interrupted_Exception&){}
		cout << "DriveTrainRobot off" << endl;
	}
};
class WheelRobot : public Runnable{
private:
	CradlePtr cradle;
public:
	WheelRobot(CradlePtr cr) : cradle(cr){}
	void run(){
		try{
			while(!Thread::interrupted()){
				cradle->offerWheelBotServices();/*Blocks until job is offered/accepted*/
				cout << "Installing Wheel" << endl;
				(*cradle)->addWheels();
				cradle->taskFinished();
			}
		}catch(Interrupted_Exception&){}
		cout << "WheelRobot off" << endl;
	}
};
class Reporter : public Runnable{
private:
	CarQueue carQueue;
public:
	Reporter(CarQueue& cq) : carQueue(cq){}
	void run(){
		try{
			while(!Thread::interrupted()){
				cout << carQueue->get() << endl;
			}
		}catch(Interrupted_Exception&){}
		cout << "Reporter off" << endl;
	}
};
int main() {
	cout << "Press <Enter> to quit" << endl;
	try{
		CarQueue chassisQueue(new TQueue<Car>), finishingQueue(new TQueue<Car>);
		CradlePtr cradle(new Cradle);
		ThreadedExecutor assemblyLine;
		assemblyLine.execute(new EngineRobot(cradle));
		assemblyLine.execute(new DriveTrainRobot(cradle));
		assemblyLine.execute(new WheelRobot(cradle));
		assemblyLine.execute(new Director(chassisQueue, finishingQueue, cradle));
		assemblyLine.execute(new Reporter(finishingQueue));
		assemblyLine.execute(new ChassisBuilder(chassisQueue));
		cin.get();
		assemblyLine.interrupt();
	}catch(Synchronization_Exception& e){
		cerr << e.what() << endl;
	}
}

 

二、实验验证

ThreadQueue created
Press <Enter> to quit
User thread created.
Reference thread created.
1 reference-thread added.
pollPendingThreads()
1 user-thread added.
Thread starting...
User thread created.
pollPendingThreads()
1 user-thread added.
Thread starting...
User thread created.
pollPendingThreads()
1 user-thread added.
Thread starting...
User thread created.
pollPendingThreads()
1 user-thread added.
Thread starting...
User thread created.
pollPendingThreads()
1 user-thread added.
Thread starting...
User thread created.
pollPendingThreads()
1 user-thread added.
Thread starting...
Car0 [  engine: 0driveTrain: 0 wheels: 0 ]
Installing engine
Installing DriveTrain
Installing Wheel
Car0 [  engine: 1driveTrain: 1 wheels: 1 ]
Car1 [  engine: 0driveTrain: 0 wheels: 0 ]
Installing engine
Installing Wheel
Installing DriveTrain
Car1 [  engine: 1driveTrain: 1 wheels: 1 ]
Car2 [  engine: 0driveTrain: 0 wheels: 0 ]
Installing DriveTrain
Installing engine
Installing Wheel
Car2 [  engine: 1driveTrain: 1 wheels: 1 ]
Car3 [  engine: 0driveTrain: 0 wheels: 0 ]
Installing Wheel
Installing DriveTrain
Installing engine
Car3 [  engine: 1driveTrain: 1 wheels: 1 ]
Car4 [  engine: 0driveTrain: 0 wheels: 0 ]
Installing engine
Installing Wheel
Installing DriveTrain
Car4 [  engine: 1driveTrain: 1 wheels: 1 ]
Car5 [  engine: 0driveTrain: 0 wheels: 0 ]
Installing engine
Installing DriveTrain
Installing Wheel
Car5 [  engine: 1driveTrain: 1 wheels: 1 ]
Car6 [  engine: 0driveTrain: 0 wheels: 0 ]
Installing Wheel
Installing DriveTrain
Installing engine
Car6 [  engine: 1driveTrain: 1 wheels: 1 ]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无色界神力

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值