前序
之前在实习的时候,leader为了锻炼我的学习能力,让我用wins api函数写一个多线程实际的应用案例,后来用MFC简单的封装一下,一个小型的类似于外卖系统抢单,派单的小逻辑~~,今天在项目运用中又遇到了需要提高效率的地方,所以想记录一下
线程池的,多线程的好处,同步,异步,互斥锁等等的概念在这里就不多说了~~
我就开门见山啦,,环境:VS2008
附上代码
Event类
class Event
{
public:
Event();
~Event();
void Wait() const;
void Notify() const;
private:
HANDLE hEvent;
};
Event类实现
Event::Event()
{
hEvent = CreateEvent(NULL,false,false,NULL);
}
Event::~ Event()
{
if(hEvent)
::CloseHandle(hEvent);
}
void Event::Wait() const
{
WaitForSingleObject(hEvent, INFINITE);
}
void Event::Notify() const
{
::SetEvent(hEvent);
}
锁Mutex
class Mutex
{
public:
Mutex();
~Mutex();
void lock() const;
void unlock() const;
private:
HANDLE m_hMutex;
};
Mutex实现
Mutex::Mutex()
{
m_hMutex = ::CreateMutex(NULL, FALSE, NULL);
}
Mutex::~ Mutex()
{
::CloseHandle(m_hMutex);
}
void Mutex::lock() const
{
WaitForSingleObject(m_hMutex, INFINITE);
}
void Mutex::unlock() const
{
::ReleaseMutex(m_hMutex);
}
Task类
class Task
{
public:
Task(int stime);
~Task();
void DoTask();
unsigned int GetTaskId();
void SetId(unsigned int Id);
void SetHandle(HWND MainHandl);
unsigned int GetRestTime();
unsigned int sp_time;
unsigned int RestTime;
unsigned int ID;
HWND m_Handle;
Mutex T_mutex;
};
Task类实现
Task::Task(int sptime)
{
sp_time = sptime;
RestTime = sp_time;
}
Task::~Task()
{
}
void Task::SetId(unsigned int Id)
{
ID = Id;
}
void Task::DoTask()
{
for (int i = 0; i <= sp_time; ++i) {
RestTime = sp_time-i;
::PostMessage(m_Handle,WM_MYMESSAGE,NULL,NULL);
Sleep(1000);
}
}
unsigned int Task::GetTaskId()
{
return ID;
}
void Task::SetHandle(HWND MainHandl)
{
m_Handle = MainHandl;
}
unsigned int Task::GetRestTime()
{
return RestTime;
}
ThreadBase类
//Class BaseThread
class BaseThread
{
public:
BaseThread();
virtual ~BaseThread();
protected:
virtual void Run();
HANDLE hThread;
DWORD dwThreadId;
};
ThreadBase类实现
DWORD WINAPI WorkThread(LPVOID lpParam);
DWORD WINAPI WorkThread1(LPVOID lpParam);
BaseThread::BaseThread()
{
}
BaseThread::~BaseThread()
{
}
void BaseThread::Run()
{
}
TaskThread类
//Class TaskThread
class ThreadPool;
class TaskThread: public BaseThread
{
public:
TaskThread();
TaskThread(int Num);
~TaskThread();
unsigned int TaskThreadNum();
void Run();
void SendTask(Task *p_Task);
void Create();
void CancleTask(HWND MainHandl);
bool GetPwork();
Task *GetTask();
bool GetPcancle();
DWORD GetThreadID(){return dwThreadId;}
Mutex s_Mutex;
Event s_Event;
Event p_Event;
static int flag;
bool p_Work;
Task *m_Task;
bool p_Cancle;
};
class MainThread: public BaseThread
{
public:
MainThread();
~MainThread();
private:
void Run();
};
TaskThread类实现
TaskThread::TaskThread()
{
hThread = CreateThread(NULL, 0, WorkThread, this, 0, &dwThreadId);
if(hThread==NULL) {
ExitProcess(dwThreadId);
}
m_Task = NULL;
p_Cancle = false;
}
MainThread::MainThread()
{
HWND MainHandle = AfxGetMainWnd()->m_hWnd;
hThread = CreateThread(NULL, 0, WorkThread1, MainHandle, 0, &dwThreadId);
if(hThread==NULL) {
ExitProcess(dwThreadId);
}
}
TaskThread::~TaskThread()
{
CloseHandle(hThread);
if (NULL != m_Task) {
delete m_Task;
m_Task = NULL;
}
}
void TaskThread::Run()
{
while(true) {
s_Event.Wait();
s_Mutex.lock();
if (NULL != m_Task) {
m_Task->DoTask();
}
m_Task = NULL;
s_Mutex.unlock();
if (p_Cancle == false) {
ThreadPool::Instance()->MoveToIdleList(this);
}
}
}
void TaskThread::SendTask(Task *p_Task)
{
s_Mutex.lock();
m_Task = p_Task;
s_Mutex.unlock();
s_Event.Notify();
}
bool TaskThread::GetPwork()
{
return p_Work;
}
Task *TaskThread::GetTask()
{
return m_Task;
}
bool TaskThread::GetPcancle()
{
return p_Cancle;
}
void TaskThread::CancleTask(HWND MainHandle)
{
p_Cancle = !p_Cancle;
if (p_Cancle == true &&this->p_Work == false) {
ThreadPool::Instance()->MoveToBusyList(this);
}
else if (p_Cancle == false && this->p_Work == true) {
ThreadPool::Instance()->MoveToIdleList(this);
}
::PostMessage(MainHandle,WM_MYMESSAGE,NULL,NULL);
}
DWORD WINAPI WorkThread(LPVOID lpParam)
{
TaskThread *pThread = (TaskThread*)lpParam;
pThread->Run();
return 0;
}
DWORD WINAPI WorkThread1(LPVOID lpParam)
{
HWND MainHdle = (HWND) lpParam;
ThreadPool::Instance()->Run(MainHdle);
return 0;
}
线程池 Threadpool
//Class ThreadPool
class ThreadPool{
public:
static ThreadPool* Instance();
ThreadPool();
~ThreadPool();
void SendTask(Task *p_Task);
//void CancelTask(Task *p_Task);
void Run(HWND MainHandle);
std::vector<TaskThread*> m_Thread;
std::vector<TaskThread*> m_BusyThread;
std::vector<TaskThread*> m_IdleThread;
std::list<Task*>m_TaskList;
Event m_TaskEvent;
Event m_IdleEvent;
Mutex m_BusyMutex;
Mutex m_IdleMutex;
Mutex m_TaskMutex;
static ThreadPool *s_ThreadPool;
unsigned int m_InitNum;
bool InstanceFlsg;
TaskThread* GetIdleThread(void);
void AppendToIdleList(TaskThread* ss_thread);
void MoveToBusyList(TaskThread* idlethread);
void MoveToIdleList(TaskThread* busythread);
};
线程池的实现
ThreadPool *ThreadPool::s_ThreadPool = NULL;
ThreadPool::ThreadPool()
{
InstanceFlsg = false;
m_InitNum = 3;
m_BusyThread.clear();
m_IdleThread.clear();
m_TaskList.clear();
for(int i = 0; i< m_InitNum; i++) {
TaskThread* thr = new TaskThread();
AppendToIdleList(thr);
}
}
ThreadPool *ThreadPool::Instance()
{
if (NULL == s_ThreadPool) {
s_ThreadPool = new ThreadPool();
}
return s_ThreadPool;
}
ThreadPool::~ThreadPool()
{
for (int i = 0; i < m_InitNum; ++i) {
if (NULL != m_Thread[i]) {
delete m_Thread[i];
m_Thread[i] = NULL;
}
}
}
TaskThread* ThreadPool::GetIdleThread(void)
{
m_IdleMutex.lock();
if (m_IdleThread.size() > 0) {
TaskThread* thr = (TaskThread*)m_IdleThread.front();
std::cout<<"The Idlethread id is "<<thr->GetThreadID()<<std::endl;
m_IdleMutex.unlock();
return thr;
}
m_IdleMutex.unlock();
return NULL;
}
void ThreadPool::MoveToBusyList(TaskThread* idlethread)
{
m_BusyMutex.lock();
m_BusyThread.push_back(idlethread);
idlethread->p_Work = true;
m_BusyMutex.unlock();
m_IdleMutex.lock();
std::vector<TaskThread*>::iterator pos;
pos = find(m_IdleThread.begin(),m_IdleThread.end(),idlethread);
if(pos !=m_IdleThread.end()) {
m_IdleThread.erase(pos);
}
m_IdleMutex.unlock();
}
void ThreadPool::MoveToIdleList(TaskThread* busythread)
{
m_IdleMutex.lock();
m_IdleThread.push_back(busythread);
busythread->p_Work = false;
m_IdleMutex.unlock();
m_BusyMutex.lock();
std::vector<TaskThread*>::iterator pos;
pos = find(m_BusyThread.begin(),m_BusyThread.end(),busythread);
if(pos!=m_BusyThread.end()) {
m_BusyThread.erase(pos);
}
m_BusyMutex.unlock();
m_IdleEvent.Notify();
}
void ThreadPool::AppendToIdleList(TaskThread* s_thread)
{
m_IdleMutex.lock();
m_IdleThread.push_back(s_thread);
s_thread->p_Work = false;
m_Thread.push_back(s_thread);
m_IdleMutex.unlock();
}
void ThreadPool::SendTask(Task* p_Task)
{
m_TaskMutex.lock();
m_TaskList.push_back(p_Task);
::PostMessage(AfxGetMainWnd()->m_hWnd,WM_MYMESSAGE,NULL,NULL);
m_TaskMutex.unlock();
m_TaskEvent.Notify();
}
void ThreadPool::Run(HWND MainHandle)
{
InstanceFlsg = true;
Task* s_Task = NULL;
while (true) {
if (m_IdleThread.size() == 0) {
m_IdleEvent.Wait();
}
else {
if (m_TaskList.size() == 0) {
m_TaskEvent.Wait();
}
else {
s_Task = *(m_TaskList.begin());
m_TaskList.pop_front();
//::Postmessage(AfxGetMainWnd()->m_hWnd , WM_MYMESSAGE , NULL ,NULL);
m_TaskMutex.lock();
::PostMessage(MainHandle,WM_MYMESSAGE,NULL,NULL);
m_TaskMutex.unlock();
if (NULL != s_Task) {
//Sleep(1000);//等待撤销的Thread
TaskThread* idlethr = GetIdleThread();
if (NULL != idlethr) {
MoveToBusyList(idlethr);
idlethr->SendTask(s_Task);
}
}
}
}
}
}
面临毕业的你们想加深对多线程的理解,可以自己去实际根据自己的想法去实装task类,显而易见的是上诉程序已经可以实现同步,即task源源不断的创建,丢到ThreadPool,ThreadPool会指派空闲的线程去这些task,能实现边丢task,变解决task~,线程之间逻辑在这里就不多说了~
有兴趣的也可以大概的去给这些task赋予优先级,即当线程不够时,优先解决优先级高的task~
同时附上之前MFC的一段关键代码
LRESULT CThreadAppDlg::OnMyMessage(WPARAM wParam, LPARAM lParam)
{
CEdit* pBoxOne1;
pBoxOne1 = (CEdit*) GetDlgItem(IDC_EDIT1);
CEdit* pBoxOne7;
pBoxOne7 = (CEdit*) GetDlgItem(IDC_EDIT7);
CEdit* pBoxOne4;
pBoxOne4 = (CEdit*) GetDlgItem(IDC_EDIT4);
CEdit* pBoxOne5;
pBoxOne5 = (CEdit*) GetDlgItem(IDC_EDIT5);
CString str;
int t =ThreadPool::Instance()->m_TaskList.size();
CString str1;
m_2 = "剩余Task数目:";
str1.Format(_T("%d"),t);
m_2 += str1;
pBoxOne1->SetWindowText(m_2);
if (ThreadPool::Instance()->m_Thread[0]->GetPwork() == true && NULL != ThreadPool::Instance()->m_Thread[0]->GetTask()) {
m_7 = "执行Task: ";
str.Format(_T("%d"),ThreadPool::Instance()->m_Thread[0]->GetTask()->GetTaskId());
m_7 += str;
if (ThreadPool::Instance()->m_Thread[0]->GetTask()->GetRestTime() != 0){
m_7+=",执行时间还剩: ";
str.Format(_T("%d"),ThreadPool::Instance()->m_Thread[0]->GetTask()->GetRestTime());
m_7 += str;
m_7 += "秒";
}
else if (ThreadPool::Instance()->m_Thread[0]->GetPcancle() ==false){
m_7 += ",Task执行完毕.等待执行新Task...";
}
else {
m_7 = "线程休息中...";
}
pBoxOne7->SetWindowText(m_7);
}
else if (ThreadPool::Instance()->m_Thread[0]->GetPcancle() ==true ||(ThreadPool::Instance()->m_Thread[0]->GetPwork() == false && ThreadPool::Instance()->m_Thread[0]->GetPcancle() ==false && ThreadPool::Instance()->m_TaskList.size() > 0)) {
m_7 = "线程休息中...";
pBoxOne7->SetWindowText(m_7);
}
else if (ThreadPool::Instance()->m_Thread[0]->GetPwork() == false && ThreadPool::Instance()->m_Thread[0]->GetPcancle() ==false) {
m_7 = "等待执行Task...";
pBoxOne7->SetWindowText(m_7);
}
if (ThreadPool::Instance()->m_Thread[1]->GetPwork() == true && NULL != ThreadPool::Instance()->m_Thread[1]->GetTask()) {
m_4 = "执行Task: ";
str.Format(_T("%d"),ThreadPool::Instance()->m_Thread[1]->GetTask()->GetTaskId());
m_4 += str;
if (ThreadPool::Instance()->m_Thread[1]->GetTask()->GetRestTime() != 0) {
m_4+=",执行时间还剩: ";
str.Format(_T("%d"),ThreadPool::Instance()->m_Thread[1]->GetTask()->GetRestTime());
m_4 += str;
m_4 += "秒";
}
else if (ThreadPool::Instance()->m_Thread[1]->GetPcancle() ==false){
m_4 += ",Task执行完毕.等待执行新Task...";
}
else {
m_4 = "线程休息中...";
}
pBoxOne4->SetWindowText(m_4);
}
else if (ThreadPool::Instance()->m_Thread[1]->GetPcancle() ==true ||(ThreadPool::Instance()->m_Thread[0]->GetPwork() == false && ThreadPool::Instance()->m_Thread[1]->GetPcancle() ==false && ThreadPool::Instance()->m_TaskList.size() > 0)) {
m_4 = "线程休息中...";
pBoxOne4->SetWindowText(m_4);
}
else if (ThreadPool::Instance()->m_Thread[1]->GetPwork() == false && ThreadPool::Instance()->m_Thread[1]->GetPcancle() ==false) {
m_4 = "等待执行Task...";
pBoxOne4->SetWindowText(m_4);
}
if (ThreadPool::Instance()->m_Thread[2]->GetPwork() == true && NULL != ThreadPool::Instance()->m_Thread[2]->GetTask()) {
m_5 = "执行Task: ";
str.Format(_T("%d"),ThreadPool::Instance()->m_Thread[2]->GetTask()->GetTaskId());
m_5 += str;
if (ThreadPool::Instance()->m_Thread[2]->GetTask()->GetRestTime() != 0){
m_5+=",执行时间还剩: ";
str.Format(_T("%d"),ThreadPool::Instance()->m_Thread[2]->GetTask()->GetRestTime());
m_5 += str;
m_5 += "秒";
}
else if (ThreadPool::Instance()->m_Thread[2]->GetPcancle() ==false){
m_5 += ",Task执行完毕.等待执行新Task...";
}
else {
m_5 = "线程休息中...";
}
pBoxOne5->SetWindowText(m_5);
}
else if (ThreadPool::Instance()->m_Thread[2]->GetPcancle() ==true ||(ThreadPool::Instance()->m_Thread[0]->GetPwork() == false && ThreadPool::Instance()->m_Thread[2]->GetPcancle() ==false && ThreadPool::Instance()->m_TaskList.size() > 0)) {
m_5 = "线程休息中...";
pBoxOne5->SetWindowText(m_5);
}
else if (ThreadPool::Instance()->m_Thread[2]->GetPwork() == false && ThreadPool::Instance()->m_Thread[2]->GetPcancle() ==false) {
m_5 = "等待执行Task...";
pBoxOne5->SetWindowText(m_5);
}
UpdateData(FALSE);
return 0;
}
看不大懂的同学欢迎留言交流~~