zthread学习 实例十一 线程间的协助(二)

例一、生产者-消费者

 

 

一个任务制作烤面包(生产者),一个任务给烤面包抹黄油(消费者),还有一个任务是往抹好黄油的烤面包上抹果酱(消费者)。

代码如下:

[cpp]  view plain copy
  1. #include "stdafx.h"  
  2. #include "zthread/FastMutex.h"  
  3. #include "zthread/CountedPtr.h"  
  4. #include "zthread/Runnable.h"  
  5. #include "zthread/Condition.h"  
  6. #include <iostream>  
  7. using namespace ZThread;  
  8. using namespace std;  
  9.   
  10. class Jammer : public Runnable  
  11. {  
  12. public:  
  13.     Jammer() : butteredToastReady(Lock), jammed(0), isGotButteredToast(false){}  
  14.       
  15.     void moreButteredToastReady()  
  16.     {  
  17.         Guard<Mutex> g(Lock);  
  18.           
  19.         isGotButteredToast = true;  
  20.         butteredToastReady.signal();  
  21.     }  
  22.       
  23.     void run()  
  24.     {  
  25.         try  
  26.         {  
  27.             while (!Thread::interrupted())  
  28.             {  
  29.                 {  
  30.                     Guard<Mutex> g(Lock);  
  31.                     while (isGotButteredToast == false)  
  32.                         butteredToastReady.wait();  
  33.                     ++jammed;  
  34.                 }  
  35.                   
  36.                 cout << "Putting jam on toast : " <<jammed <<endl;  
  37.                   
  38.                 {  
  39.                     Guard<Mutex> g(Lock);  
  40.                       
  41.                     isGotButteredToast = false;  
  42.                   
  43.                 }  
  44.             }  
  45.         }  
  46.         catch (Interrupted_Exception& e)  
  47.         {  
  48.             cout << " Jarry : "<< e.what() <<endl;  
  49.         }  
  50.     }  
  51. private:  
  52.     Mutex       Lock;  
  53.     Condition   butteredToastReady;  
  54.     bool        isGotButteredToast;  
  55.       
  56.     int         jammed;  
  57. };  
  58. class Butterer : public Runnable  
  59. {  
  60. public:  
  61.     Butterer(CountedPtr<Jammer>& j) : toastReady(Lock), jammer(j), Buttered(0), isGotToast(false){}  
  62.       
  63.     void moreToastReady()  
  64.     {  
  65.         Guard<Mutex> g(Lock);  
  66.         isGotToast = true;  
  67.         toastReady.signal();  
  68.     }  
  69.       
  70.     void run()  
  71.     {  
  72.         try  
  73.         {  
  74.             while (!Thread::interrupted())  
  75.             {  
  76.                 {  
  77.                     Guard<Mutex> g(Lock);  
  78.                       
  79.                     while (!isGotToast)  
  80.                         toastReady.wait();  
  81.                           
  82.                     ++Buttered;  
  83.                 }  
  84.                 cout << "Buttering toast :" << Buttered <<endl;  
  85.                 jammer->moreButteredToastReady();  
  86.                   
  87.                 {  
  88.                     Guard<Mutex> g(Lock);  
  89.                     isGotToast = false;  
  90.                 }  
  91.             }  
  92.         }  
  93.         catch (Interrupted_Exception& e)  
  94.         {  
  95.             cout << " Jarry " << e.what() << endl;              
  96.         }  
  97.     }  
  98.       
  99. private:  
  100.     Mutex               Lock;  
  101.     Condition           toastReady;  
  102.     CountedPtr<Jammer>    jammer;  
  103.     bool                isGotToast;  
  104.     int                 Buttered;  
  105. };  
  106. class Toast : public Runnable  
  107. {  
  108. public:  
  109.     Toast(CountedPtr<Butterer>& aButterer) : butterer(aButterer), toasted(0) {}  
  110.       
  111.     void run()  
  112.     {  
  113.         try  
  114.         {  
  115.             while (!Thread::interrupted())  
  116.             {  
  117.                 Thread::sleep(1000);  
  118.                   
  119.                 cout << "A new Toast" << ++toasted <<endl;  
  120.                   
  121.                 butterer->moreToastReady();  
  122.             }  
  123.         }  
  124.         catch (Interrupted_Exception& e)  
  125.         {  
  126.             cerr << "Jarry " << e.what() <<endl;  
  127.         }  
  128.     }  
  129. private:  
  130.     CountedPtr<Butterer> butterer;  
  131.     int toasted;  
  132. };  
  133.   
  134. int _tmain(int argc, _TCHAR* argv[])   
  135. {  
  136.     try  
  137.     {  
  138.         CountedPtr<Jammer>        jammer(new Jammer);  
  139.         CountedPtr<Butterer>  butterer(new Butterer(jammer));  
  140.         CountedPtr<Toast>     toast(new Toast(butterer));  
  141.           
  142.         ThreadedExecutor executor;  
  143.         executor.execute(toast);  
  144.         executor.execute(jammer);  
  145.         executor.execute(butterer);  
  146.         cin.get();  
  147.         executor.interrupt();  
  148.     }  
  149.     catch (Synchronization_Exception& e)  
  150.     {  
  151.         cerr <<" Jarry Main " << e.what() <<endl;  
  152.     }  
  153.       
  154.     return 0;  
  155. }  
 

 

 

 

线程处理问题常常基于需要对任务进行串行化处理。使用队列可以采用同步的方式访问其内部元素,这样可以解决很多线程处理问题,下面基于STL中的deque实现的队列:

[cpp]  view plain copy
  1. #ifndef QUEUE_H  
  2. #define QUEUE_H  
  3. #include "zthread/Runnable.h"  
  4. #include "zthread/PoolExecutor.h"    
  5.   
  6. template<class T>   
  7. class TQueue  
  8. {  
  9.     //锁子    
  10.     ZThread::Mutex lock;    
  11.     //线程协作基类    
  12.     ZThread::Condition cond;    
  13.     //线程队列元素    
  14.     std::deque<T> data;    
  15. public:    
  16.     TQueue() : cond(lock) {}    
  17.     void put(T item)     
  18.     {    
  19.         ZThread::Guard<ZThread::Mutex> g(lock);    
  20.         data.push_back(item);    
  21.         cond.signal();  
  22.     }    
  23.     T get()     
  24.     {    
  25.         ZThread::Guard<ZThread::Mutex> g(lock);    
  26.         while(data.empty())    
  27.             cond.wait();    
  28.         T returnVal = data.front();    
  29.         data.pop_front();  
  30.         return returnVal;    
  31.     }    
  32. };    
  33. #endif  
 

 

1、加入同步以确保在同一时刻不会有两个线程添加对象。

2、加入wait()和signal()在队列空时,挂起线程,并在有多个元素可用时恢复执行。

 

 

 

二、广播

 

signal()函数唤醒了一个正在等待Condition对象的线程。然而,也许会有多个线程在等待某个相同的条件对象,在这种情况下需要使用broadcast()(与调用线程的个数的signal()效果相同)而不是signal()把这些线程唤醒。

 

 

 

使用广播的例子:每辆Car将在几个阶段内装配完成,本例中将看到这样一个阶段:底盘制作好之后的这段时间里可以 同时 安装发动机、驱动传动装置和车轮(广播)。本例中综合中前面中所有关于线程的知识。

[cpp]  view plain copy
  1. #include <iostream>    
  2. #include <string>    
  3. #include "zthread/Thread.h"    
  4. #include "zthread/Mutex.h"    
  5. #include "zthread/Guard.h"    
  6. #include "zthread/Condition.h"    
  7. #include "zthread/ThreadedExecutor.h"    
  8. #include "TQueue.h"    
  9. using namespace ZThread;    
  10. using namespace std;    
  11. //driveTrain 驱动传动    
  12. class Car   
  13. {    
  14.     int     id;    
  15.     bool    engine, driveTrain, wheels;    
  16. public:    
  17.     Car(int idn) : id(idn), engine(false),    
  18.         driveTrain(false), wheels(false) {}    
  19.     // Empty Car object:    
  20.     Car() : id(-1), engine(false),    
  21.         driveTrain(false), wheels(false) {}   
  22.     // Unsynchronized -- assumes atomic bool operations:    
  23.     int getId() { return id; }    
  24.     void addEngine() { engine = true; }    
  25.     bool engineInstalled() { return engine; }   
  26.     void addDriveTrain() { driveTrain = true; }    
  27.     bool driveTrainInstalled() { return driveTrain; }   
  28.     void addWheels() { wheels = true; }    
  29.     bool wheelsInstalled() { return wheels; }    
  30.     friend ostream& operator<<(ostream& os, const Car& c)  
  31.     {  
  32.         return os << "Car " << c.id << " ["  
  33.             << " engine: " << c.engine  
  34.             << " driveTrain: " << c.driveTrain  
  35.             << " wheels: " << c.wheels << " ]";  
  36.     }  
  37. };    
  38. typedef CountedPtr< TQueue<Car> > CarQueue;    
  39. class ChassisBuilder : public Runnable  
  40. {  
  41.     CarQueue    carQueue;   
  42.     int         counter;  
  43. public:    
  44.     ChassisBuilder(CarQueue& cq) : carQueue(cq),counter(0) {}    
  45.     void run()  
  46.     {  
  47.         try   
  48.         {  
  49.             while(!Thread::interrupted())   
  50.             {  
  51.                 Thread::sleep(100);   
  52.                 // Make chassis:    
  53.                 Car c(counter++);  
  54.                 cout << c << endl;    
  55.                 // Insert into queue  
  56.                 carQueue->put(c);  
  57.             }  
  58.         }   
  59.         catch(Interrupted_Exception&) { /* Exit */ }  
  60.         cout << "ChassisBuilder off" << endl;    
  61.     }    
  62. };    
  63. class Cradle  
  64. {  
  65.     Car         c; // Holds current car being worked on    
  66.     bool        occupied;  
  67.     Mutex       workLock, readyLock;  
  68.     Condition   workCondition, readyCondition;  
  69.     bool        engineBotHired, wheelBotHired, driveTrainBotHired;  
  70. public:    
  71.     Cradle()    
  72.     : workCondition(workLock), readyCondition(readyLock)  
  73.     {    
  74.             occupied            = false;  
  75.             engineBotHired      = true;  
  76.             wheelBotHired       = true;  
  77.             driveTrainBotHired  = true;  
  78.     }    
  79.     //向底盘生产线中加入car对象    
  80.     //并修改底盘生产线的状态(被占用)    
  81.     void insertCar(Car chassis)   
  82.     {  
  83.         c = chassis;  
  84.         occupied = true;  
  85.     }  
  86.     //从底盘生产线中取出对象    
  87.     //修正状态为未被占用,并返回car对象  
  88.     Car getCar()   
  89.     {  
  90.         // Can only extract car once    
  91.         if(!occupied)  
  92.         {    
  93.             cerr << "No Car in Cradle for getCar()" << endl;    
  94.             return Car(); // "Null" Car object    
  95.         }   
  96.         occupied = false;    
  97.         return c;    
  98.     }    
  99.     // Access car while in cradle:    
  100.     //重载指向成员符号    
  101.     //可以使用(*Cradle)直接调用  
  102.     Car* operator->() { return &c; }  
  103.     // Allow robots to offer services to this cradle:  
  104.     void offerEngineBotServices()  
  105.     {  
  106.         Guard<Mutex> g(workLock);  
  107.         while(engineBotHired)    
  108.             workCondition.wait();  
  109.         engineBotHired = true// Accept the job    
  110.     }  
  111.     void offerWheelBotServices()   
  112.     {    
  113.         Guard<Mutex> g(workLock);  
  114.         while(wheelBotHired)    
  115.             workCondition.wait();  
  116.         //这个wait被挂起,直到收到了startWork()的广播    
  117.         //在startWork()中,雇佣的状态会被修改,因此下一步的操作是修正状态    
  118.         wheelBotHired = true// Accept the job    
  119.     }    
  120.     void offerDriveTrainBotServices()  
  121.     {    
  122.         Guard<Mutex> g(workLock);    
  123.         while(driveTrainBotHired)    
  124.             workCondition.wait();    
  125.         driveTrainBotHired = true// Accept the job    
  126.     }    
  127.     // Tell waiting robots that work is ready:   
  128.     void startWork()  
  129.     {    
  130.         Guard<Mutex> g(workLock);    
  131.         engineBotHired      = false;    
  132.         wheelBotHired       = false;    
  133.         driveTrainBotHired  = false;    
  134.         workCondition.broadcast(); //等价于3个signal()  
  135.         //workCondition.signal();   
  136.         //workCondition.signal();   
  137.         //workCondition.signal();   
  138.     }   
  139.     // Each robot reports when their job is done:    
  140.     void taskFinished()   
  141.     {    
  142.         Guard<Mutex> g(readyLock);   
  143.         //Guard<Mutex> g(workLock);   
  144.         readyCondition.signal();  
  145.     }    
  146.     // Director waits until all jobs are done:    
  147.     void waitUntilWorkFinished()  
  148.     {    
  149.         Guard<Mutex> g(readyLock);  
  150.         while(!(c.engineInstalled() && c.driveTrainInstalled() && c.wheelsInstalled()))    
  151.             readyCondition.wait();  
  152.     }  
  153. };  
  154.   
  155. typedef CountedPtr<Cradle> CradlePtr;    
  156. class Director : public Runnable  
  157. {    
  158.     CarQueue    chassisQueue, finishingQueue;  
  159.     CradlePtr   cradle;  
  160. public:  
  161.     Director(CarQueue& cq, CarQueue& fq, CradlePtr cr)    
  162.         : chassisQueue(cq), finishingQueue(fq), cradle(cr) {}    
  163.     void run()   
  164.     {  
  165.         try  
  166.         {  
  167.             while(!Thread::interrupted())  
  168.             {  
  169.                 // Blocks until chassis is available:    
  170.                 cradle->insertCar(chassisQueue->get());  
  171.                 // Notify robots car is ready for work  
  172.                 cradle->startWork();  
  173.                 // Wait until work completes    
  174.                 cradle->waitUntilWorkFinished();  
  175.                 // Put car into queue for further work    
  176.                 finishingQueue->put(cradle->getCar());   
  177.             }    
  178.         }  
  179.         catch(Interrupted_Exception&) { /* Exit */ }  
  180.         cout << "Director off" << endl;    
  181.     }    
  182. };  
  183.   
  184. class EngineRobot : public Runnable  
  185. {    
  186.     CradlePtr cradle;  
  187. public:    
  188.     EngineRobot(CradlePtr cr) : cradle(cr) {}    
  189.     void run()   
  190.     {    
  191.         try  
  192.         {    
  193.             while(!Thread::interrupted())  
  194.             {  
  195.                 // Blocks until job is offered/accepted:    
  196.                 cradle->offerEngineBotServices();  
  197.                 cout << "Installing engine" << endl;   
  198.                 (*cradle)->addEngine();          //隐式的调用了operator->()还是隐式的类型转换?    
  199.                 cradle->taskFinished();    
  200.             }    
  201.         }   
  202.         catch(Interrupted_Exception&) { /* Exit */ }   
  203.         cout << "EngineRobot off" << endl;  
  204.     }  
  205. };  
  206.   
  207. class DriveTrainRobot : public Runnable  
  208. {    
  209.     CradlePtr cradle;    
  210. public:    
  211.     DriveTrainRobot(CradlePtr cr) : cradle(cr) {}  
  212.     void run()   
  213.     {    
  214.         try   
  215.         {    
  216.             while(!Thread::interrupted())  
  217.             {    
  218.                 // Blocks until job is offered/accepted:    
  219.                 cradle->offerDriveTrainBotServices();  
  220.                 cout << "Installing DriveTrain" << endl;  
  221.                 (*cradle.operator ->())->addDriveTrain();   
  222.                 cradle->taskFinished();    
  223.             }    
  224.         }   
  225.         catch(Interrupted_Exception&) { /* Exit */ }   
  226.         cout << "DriveTrainRobot off" << endl;    
  227.     }    
  228. };    
  229. class WheelRobot : public Runnable  
  230. {    
  231.     CradlePtr cradle;    
  232. public:    
  233.     WheelRobot(CradlePtr cr) : cradle(cr) {}    
  234.     void run()   
  235.     {    
  236.         try  
  237.         {    
  238.             while(!Thread::interrupted())   
  239.             {    
  240.                 // Blocks until job is offered/accepted:    
  241.                 cradle->offerWheelBotServices();    
  242.                 cout << "Installing Wheels" << endl;  
  243.                 (*cradle)->addWheels();    
  244.                 cradle->taskFinished();    
  245.             }    
  246.         }   
  247.         catch(Interrupted_Exception&) { /* Exit */ }    
  248.         cout << "WheelRobot off" << endl;    
  249.     }  
  250. };  
  251.   
  252. class Reporter : public Runnable  
  253. {    
  254.     CarQueue carQueue;    
  255. public:    
  256.     Reporter(CarQueue& cq) : carQueue(cq) {}    
  257.     void run()  
  258.     {  
  259.         try   
  260.         {    
  261.             while(!Thread::interrupted())   
  262.             {    
  263.                 cout << carQueue->get() << endl;    
  264.             }    
  265.         }   
  266.         catch(Interrupted_Exception&) { /* Exit */ }    
  267.         cout << "Reporter off" << endl;    
  268.     }    
  269. };  
  270.   
  271. int main() {    
  272.     cout << "Press <Enter> to quit" << endl;    
  273.     try {    
  274.         CarQueue chassisQueue(new TQueue<Car>),  finishingQueue(new TQueue<Car>);   
  275.         CradlePtr cradle(new Cradle);    
  276.           
  277.         ThreadedExecutor assemblyLine;    
  278.         assemblyLine.execute(new EngineRobot(cradle));    
  279.         assemblyLine.execute(new DriveTrainRobot(cradle));    
  280.         assemblyLine.execute(new WheelRobot(cradle));    
  281.         assemblyLine.execute(new Director(chassisQueue, finishingQueue, cradle));  
  282.         assemblyLine.execute(new Reporter(finishingQueue));    
  283.         // Start everything running by producing chassis:    
  284.         assemblyLine.execute(new ChassisBuilder(chassisQueue));    
  285.         cin.get();    
  286.         assemblyLine.interrupt();    
  287.     } catch(Synchronization_Exception& e) {    
  288.         cerr << e.what() << endl;    
  289.     }    
  290. ///:~    
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值