池:
线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙。如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助线程但线程的数目永远不会超过最大值。超过最大值的线程可以排队,但他们要等到其他线程完成后才启动。
一 定义自己的线程
#pragma once
#ifndef MYTHREAD
#define MYTHREAD
#include <iostream>
#include <windows.h>
//线程要做的事情
typedef unsigned int(*jobFunction)(int num,WPARAM wParam, LPARAM lParam);
//线程完成后回调
typedef void(*jobCallback)(unsigned int pResult);
class MyThread
{
public:
MyThread();
~MyThread();
bool isWorking();//是否在工作
void doJob(jobFunction jobPrac, int num,WPARAM wParam, LPARAM lParam, jobCallback cb); //指派任务
private:
bool bIsWorking;
jobFunction m_jobFunc;
jobCallback m_jobCallback;
int num;
WPARAM wParam;
LPARAM lParam;
HANDLE m_pHread;
void jobDone();// 线程挂起
static DWORD WINAPI threadProc(LPARAM lParam); //真正线程
};
#endif // MYTHREAD
#include "Mythread.h"
MyThread::MyThread()
{
bIsWorking = false;
m_jobFunc = 0;
m_jobCallback = 0;
num = 0;
wParam = 0;
lParam = 0;
//m_pHread = INVALID_HANDLE_VALUE;
//创建线程
m_pHread = CreateThread(0,0,(LPTHREAD_START_ROUTINE)threadProc,this,0,0);
printf("new thread %08x\n",m_pHread);
}
MyThread::~MyThread()
{
//if (m_pHread != INVALID_HANDLE_VALUE)
//{
// TerminateThread(m_pHread,0); //强制自杀
//}
if (m_pHread != INVALID_HANDLE_VALUE)
{
m_jobCallback = (jobCallback)INVALID_HANDLE_VALUE;
m_jobFunc = (jobFunction)INVALID_HANDLE_VALUE;
ResumeThread(m_pHread);
WaitForSingleObject(m_pHread,INFINITE);
CloseHandle(m_pHread);
}
}
bool MyThread::isWorking()
{
return this->bIsWorking;
}
void MyThread::jobDone()
{
this->bIsWorking = false;
SuspendThread(m_pHread); //休眠
//printf("thread %08x job done\n",m_pHread);
}
/*
执行一个具体的任务
*/
void MyThread::doJob(jobFunction jobPrac,int num, WPARAM wParam, LPARAM lParam, jobCallback cb)
{
this->num = num;
this->m_jobCallback = cb;
this->m_jobFunc = jobPrac;
this->wParam = wParam;
this->lParam = lParam;
ResumeThread(m_pHread); //ResumeThread()使用该函数能够激活线程的运行,
//使CPU分配资源让线程恢复运行。
printf("thread %08x start work..num %d wParam %d lParam %d\n",m_pHread, num,wParam, lParam);
}
/*
真正的线程函数
*/
DWORD WINAPI MyThread::threadProc(LPARAM lParam)
{
MyThread *pthis = (MyThread *)lParam;
while (true)
{ //因为线程在构造函数中申请的,但是申请的时候没有具体的任务
if (pthis->m_jobCallback == INVALID_HANDLE_VALUE || pthis->m_jobFunc == INVALID_HANDLE_VALUE)
{
printf("thread %08x see byebye",pthis->m_pHread);
break;
}
if (pthis->m_jobCallback == 0 || pthis->m_jobFunc == 0)
{
pthis->jobDone();
//return; 不能直接return
//continue;
}
pthis->bIsWorking = true;
unsigned int result = pthis->m_jobFunc(pthis->num,pthis->wParam,pthis->lParam);
printf("thread %08x job result %d\n",pthis->m_pHread,result);
pthis->m_jobCallback(result);
pthis->jobDone();
}
return 0;
}
二 创建线程池
#pragma once
#include <vector>
#include "Mythread.h"
using namespace std;
#ifndef MYPOOL
#define MYPOOL
/*
池的概念:预先从操作系统申请大片资源,然后使用后不还给系统,保持复用
优点:避免频繁从应用层切换到内核<操作系统申请资源需要嵌入内核当中去>
*/
/*
线程池管理类,需要作为一个管理者,管理N个线程
*/
class MyPool
{
public:
MyPool(int nSize);
~MyPool();
bool pushJob(jobFunction jobPrac, int num,WPARAM wParam, LPARAM lParam, jobCallback cb);
int getPoolSize();
private:
vector<MyThread *>m_threadVector;
};
#endif // !MYPOOL
#include "Mypool.h"
//在构造在初始化几个线程
MyPool::MyPool(int nSize)
{
m_threadVector.clear();
for (int i = 0; i < nSize; ++i)
{
MyThread *tmp = new MyThread();
m_threadVector.push_back(tmp);
}
}
MyPool::~MyPool()
{
vector<MyThread *>::iterator iter = m_threadVector.begin();
for (; iter != m_threadVector.end(); iter++)
{
MyThread *tmp = *iter;
delete tmp;
}
}
bool MyPool::pushJob(jobFunction jobPrac, int num,WPARAM wParam, LPARAM lParam, jobCallback cb)
{
vector<MyThread *>::iterator iter = m_threadVector.begin();
for (;iter != m_threadVector.end();iter++)
{
MyThread *tmp = *iter;
if (!tmp->isWorking())
{
tmp->doJob(jobPrac, num,wParam, lParam, cb);
return true;
}
}
MyThread *tmp = new MyThread();
m_threadVector.push_back(tmp);
tmp->doJob(jobPrac,num, wParam, lParam, cb);
return true;
}
int MyPool::getPoolSize()
{
return m_threadVector.size();
}
三 启动线程池
#include <mutex>
#include "Mypool.h"
//typedef unsigned int(*jobFunction)(WPARAM wParam, LPARAM lParam);
//typedef void(*jobCallback)(unsigned int pResult);
mutex m;
unsigned int job(WPARAM wParam, LPARAM lParam)
{
m.lock();
printf("job doing :%d + %d = ?\n", wParam, lParam);
//Sleep(500);
return lParam + wParam;
m.unlock();
}
unsigned int job1(int num,WPARAM wParam, LPARAM lParam)
{
printf("job doing :1+2+3+...+%d= ?\n", num);
return num *(num -1)/2;
}
void cb(unsigned int pResult)
{
printf("job result:%d\n",pResult);
}
int main()
{
MyPool *pool = new MyPool(2);
while (true)
{
char cmd = getchar();
if (cmd == 'q' || cmd == 'Q')
{
break;
}
printf("thread pool size :%d\n",pool->getPoolSize());
pool->pushJob(job1,100,0,0,cb);
}
printf("process exit\n");
return 0;
}