多线程模型一:只完成最新任务

这个具体的应用场景就是QQ的历史记录管理器里面。当你点击某个联系人时,有个工作线程会去数据库查询对应的聊天记录,一次点击对应一个查询任务。

    1.当没有点击时,线程处于等待状态,一旦有点击,有查询任务,线程唤醒并执行任务。

    2.在线程执行过程中,如果用户又多次点击,只需要执行最后一个点击产生的查询任务即可。

    对应这个需求,我抽象出了一个多线程模型的实现。

OnlyRunNewestTask.h---------------------------begin--------------------------------

#pragma once

namespace ecs
{
namespace threadModal
{

class ECSUTIL_DllExport Task
{
public:
 virtual ~Task()
 {

 }

 virtual void Run() = 0;
};

class ECSUTIL_DllExport OnlyRunNewestTaskThread : public  ctk::SimpleThread
{
public:
 OnlyRunNewestTaskThread()
  :ctk::SimpleThread(0, "OnlyRunNewestTaskThread")
  ,m_mtx()
  ,m_pTask(NULL)
  ,m_updated(false)
  ,m_break(false)
 {
  
 };

 virtual ~OnlyRunNewestTaskThread() 
 {
  
 };

 void UpdateTask(Task* _data);
 bool GetTask(Task** task);
 void Break();

protected:
 virtual void run();

private:
 typedef ctk::Monitor<ctk::Mutex> _Mutex;

 _Mutex m_mtx; 
 Task* m_pTask; 
 bool m_updated;
 volatile bool m_break;
};

}
}

OnlyRunNewestTask.h---------------------------end--------------------------------

 

OnlyRunNewestTask.cpp---------------------------begin--------------------------------

#include "ecsutil_prec.h"
#include "ecsutil/threadModal/OnlyRunNewestTask.h"

using namespace ecs::threadModal;

void OnlyRunNewestTaskThread::UpdateTask(Task* _data)

 _Mutex::Lock lck(m_mtx);
 delete m_pTask;
 m_pTask = _data;
 m_updated = true;
 m_mtx.notify();
}

bool OnlyRunNewestTaskThread::GetTask(Task** task)
{
 _Mutex::Lock lck(m_mtx);
 if (!m_updated)
 {
  m_mtx.wait();
 }
 if (m_updated) 
 {
  *task = m_pTask;
  m_pTask = NULL;
  m_updated = false;
  return true;
 }
 return false;
}

void OnlyRunNewestTaskThread::Break()
{
 m_break = true;
 UpdateTask(NULL);
}

void OnlyRunNewestTaskThread::run()
{
 Task* taskData = NULL;
 while(GetTask(&taskData) && !m_break)
 {
  taskData->Run();
  delete taskData;
 }
}

OnlyRunNewestTask.cpp---------------------------end--------------------------------

 

    这种场景用这种解决方案是合适的。这个实现还有个缺点,在新任务来的时候,没有考虑中止执行旧任务。

    Task在这里就是个空壳,作用是为了抽离出独立的多线程模型代码。外界要使用这个实现代码,只需要写个具体的任务类,然后继承Task即可。要达到一样的效果,有没有更好的实现,求高手指教。

 

原文地址:https://www.cnblogs.com/towik/p/3199691.html