使用线程间通信之条件变量

发布时间:2017-7-9 7:32:39编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"使用线程间通信之条件变量 ",主要涉及到使用线程间通信之条件变量 方面的内容,对于使用线程间通信之条件变量 感兴趣的同学可以参考一下。

近期用C++写安卓下的一个通讯程序。作为jni库给java调用,採用多线程轮询遇到一个问题描写叙述例如以下:
A线程收到数据,放入队列,是生产者。
B、C、D若干个线轮询训消息队列,假设队列有数据就取出进行处理,没数据就Sleep(T)歇息,问题是这个T值取多大合适?取大了消息处理不及时。取小了手机cpu上升电池非常快耗光。



这个问题最佳解法是採用条件变量,能够比較完美解决这个问题。下面代码使用C++封装,用win32 SDK的条件变量举例,Linux下有全然等价的概念:

// 线程消息通知class ThreadMsgNotify{   // 条件变量和临界变量   CONDITION_VARIABLE cv_;   CRITICAL_SECTION cs_;public:   ThreadMsgNotify();   ~ThreadMsgNotify();   int Wait(DWORD ms);  // 消费者调用此函数,阻塞等待毫秒数   void Notify();  //  生产者调用此函数: 发出通知};

各成员方法实现例如以下:

// ---------------------------------------ThreadMsgNotify::ThreadMsgNotify(){   InitializeConditionVariable(&cv_);   InitializeCriticalSection(&cs_);}ThreadMsgNotify::~ThreadMsgNotify(){   WakeAllConditionVariable(&cv_);  // 唤醒所有线程   Sleep(50);   DeleteCriticalSection(&cs_);   DeleteConditionVariable(&cv_);}int ThreadMsgNotify::Wait(DWORD ms)  // 消费者,阻塞等待毫秒数{   EnterCriticalSection(&cs_);   int ret = SleepConditionVariableCS(&cv_, &cs_, ms);  // 等待   LeaveCriticalSection(&cs_);   return(ret);}void ThreadMsgNotify::Notify()  // 生产者: 发出通知{   EnterCriticalSection(&cs_);   WakeConditionVariable(&cv_);  // 唤醒一个等待线程(假设有的话)   LeaveCriticalSection(&cs_);}// --------------

上面的代码非常easy。差点儿不用解释。

以下再给出測试代码:

class TagThreadNotifyTest{  private:     list<string> msgList;     bool isEnd = false;     CRITICAL_SECTION cs_;  public:     int no;     ThreadMsgNotify threadNotify;  // 线程通知,接收队列收到消息时通过该对象唤醒处理线程     TagThreadNotifyTest();     ~TagThreadNotifyTest();     void New(const char* info);  // 生产者添加一条消息     int Recv(string& msg);  // 消费者读取一条消息,返回读取前队列中的消息数     // 消费者线程函数     static LRESULT WINAPI ProcThread(void* lParam);};// 辅助函数。获取当前时间戳void CurTime(char* timeStr){   SYSTEMTIME st;   GetLocalTime(&st);   sprintf(timeStr, "%02d:%02d:%02d.%03d", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);}TagThreadNotifyTest::TagThreadNotifyTest(){  InitializeCriticalSection(&cs_);  // 创建3个消费者线程  for(int i=0; i<3; i++){     no = i;     DWORD dwThreadid;     HANDLE thd = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ProcThread,                (void*)this, 0, &dwThreadid);     CloseHandle(thd);     Sleep(30);  }}TagThreadNotifyTest::~TagThreadNotifyTest(){  isEnd = true;  Sleep(100);  DeleteCriticalSection(&cs_);}// 生产者将新消息放入队列void TagThreadNotifyTest::New(const char* info){   // 加锁后插入队列   EnterCriticalSection(&cs_);      msgList.push_back(info);   LeaveCriticalSection(&cs_);   threadNotify.Notify();  // 通知其它线程,去处理数据   printf("notify...\n");}// 消费者读取消息。假设没有将返回0int TagThreadNotifyTest::Recv(string& msg){   EnterCriticalSection(&cs_);      int n = msgList.size();      if( n>0 ){          msg = msgList.front();          msgList.pop_front();      }   LeaveCriticalSection(&cs_);   return(n);}// 消费者线程LRESULT WINAPI TagThreadNotifyTest::ProcThread(void* lParam){  TagThreadNotifyTest * test = (TagThreadNotifyTest *)lParam;  int no = test->no;  printf("Thread start,  no=%d...\n", no);  char timeStr[80];  while( !test->isEnd ){     string msg;     int ret = test->Recv(msg);  // 读取一条消息     CurTime(timeStr);     if( ret ){  // 假设有就打印出来        printf(" [%d %s]Recv: %s\n", no, timeStr, msg.c_str());        Sleep(1000);  // 延时1秒模拟处理较慢的情况        continue;     }     else{  // 没有收到        printf(" [%d %s]...\n", no, timeStr);     }      // 歇息15秒,假设有通知则会随时结束歇息     test->threadNotify.Wait(15000);  }  printf("Thread End : no=%d.\n", no);  return(1);}int main(){   // 控制台測试程序   // new一个測试对象,此对象会创建3个消费者线程   TagThreadNotifyTest* test = new TagThreadNotifyTest();   // 作为生产者线程。就是接收你的按键,回车后产生一条消息   while(true){       char s[500];       memset(s, 0, 500);       gets(s);       if( strcmp(s, "exit")==0 ){           break;       }       if( s[0]=='\0' )           continue;       // 提交消息       test->New(s);   }   delete test;   return(0);}

在windows和Linux下(替换成相应函数)均測试通过。

输入一个回车后,消费者线程将马上取到消息并打印出来。假设没有消息。则消费者线程等待15秒。CPU非常轻松。





上一篇:再谈消息队列技术
下一篇:sim的准确识别技术

相关文章

相关评论

本站评论功能暂时取消,后续此功能例行通知。

一、不得利用本站危害国家安全、泄露国家秘密,不得侵犯国家社会集体的和公民的合法权益,不得利用本站制作、复制和传播不法有害信息!

二、互相尊重,对自己的言论和行为负责。

好贷网好贷款