.h头文件
#ifndef MYTHREADPOOL_H
#define MYTHREADPOOL_H
#include <windows.h>
#include <list>
#include <queue>
#include <process.h>
using namespace std;
/*
* 线程池:预先创建一些线程,使它们处于睡眠状态,不占CPU 当来任务时,唤醒线程
* 步骤:
* 1.创建一些线程
* 2.销毁线程
* 3.投递任务
* 4.线程函数
* 注意事项:
* 1.线程数量 CPU*2
* 2.线程并发 --- 线程同步解决并发问题
* 3.内存泄露 线程空间注意释放
* 4.死锁 : 加了4把锁 注意死锁问题
* 应用场景:
* 提高效率的进程
*/
//定义
class Itask
{
public:
Itask()
{
}
virtual ~Itask()
{
}
public:
virtual void Run() = 0;
};
class MyThreadPool
{
public:
MyThreadPool();
//定义
public:
//1.创建线程池:提高效率
bool CreateThreadPool(long lMinThreadNum,long lMaxThreadNum);
//2.销毁线程
void DestroyThreadPool();
//3.投递任务
bool Push(Itask *);
//4.线程函数
//DWORD WINAPI ThreadProc(LPVOID lpParam);
static unsigned _stdcall ThreadProc(void *);
private:
std::list<HANDLE> m_lstThread;//用来存放创建线程返回的句柄
std::queue<Itask*> m_qItask;//队列存放任务,解决参数覆盖问题
bool m_bFlagThread;
HANDLE m_hSemaphore;
long m_lMaxThreadNums;//最多能用的线程个数
long m_lCreateThreadNums;//目前创建的线程个数
long m_lRunThreadNums;//目前运行线程的个数
HANDLE M_hMutex;
};
#endif // MYTHREADPOOL_H
线程池.cpp
#include "mythreadpool.h"
MyThreadPool::MyThreadPool()
{
m_bFlagThread = true;
m_lMaxThreadNums = 0;
m_lCreateThreadNums = 0;
m_lRunThreadNums = 0;
M_hMutex = CreateMutexW(
0,//安全属性
0,//初始拥有权
0 //名字
);
}
bool MyThreadPool::CreateThreadPool(long lMinThreadNum,long lMaxThreadNum)
{
//1.校验参数
if (lMinThreadNum<0 || lMinThreadNum>lMaxThreadNum)
return false;
//线程资源
m_hSemaphore = CreateSemaphoreW(0,0,lMaxThreadNum,0);
//2.创建一些线程
for(long i = 0; i < lMinThreadNum; i++)
{
//_beginthreadex && CreateThread 区别
//c++运行库里的函数
//_beginthreadex(创建内存块 调用CreateThread )
//_endthreadex (销毁内存块 调用ExitThread)
//windowsAPI
//CreateThread
//ExitThread
HANDLE hThread = (HANDLE)_beginthreadex(0,0,&MyThreadPool::ThreadProc,this,0,0);
if (hThread)
//将线程存放到链表中
m_lstThread.push_back(hThread);
}
m_lMaxThreadNums = lMaxThreadNum;
m_lCreateThreadNums =lMinThreadNum;
return true;
}
bool MyThreadPool::Push(Itask* pItask)
{
//校验参数
if (!pItask)
return false;
WaitForSingleObject(M_hMutex,INFINITE);
//将任务加到队列里
m_qItask.push(pItask);//STL队列里面不允许pop push同时进行,所以pop push 都需要加锁
ReleaseMutex(M_hMutex);
//释放信号量
//ReleaseSemaphore(m_hSemaphore,1,0);
//1.有空闲的线程
if (m_lRunThreadNums < m_lCreateThreadNums)
{
ReleaseSemaphore(m_hSemaphore,1,0);
}
//2.没有空闲的线程,也还没可达到上限·
else if (m_lRunThreadNums == m_lCreateThreadNums && m_lCreateThreadNums<m_lMaxThreadNums)
{
HANDLE hThread = (HANDLE)_beginthreadex(0,0,&MyThreadPool::ThreadProc,this,0,0);
if (hThread)
m_lstThread.push_back(hThread);
ReleaseSemaphore(m_hSemaphore,1,0);
m_lCreateThreadNums++;
}
//3.爆满
else
{
ReleaseSemaphore(m_hSemaphore,1,0);
}
return true;
}
unsigned _stdcall MyThreadPool::ThreadProc(void *lpvoid)
{
MyThreadPool *pthis = (MyThreadPool*)lpvoid;
Itask *pItask = NULL;
while (pthis->m_bFlagThread)
{
//阻塞等信号
WaitForSingleObject(pthis->m_hSemaphore,INFINITE);
//阻塞-就绪-运行
//pthis->m_lRunThreadNums++;
//解决线程并发问题,不允许多跟线程同时++ 原子访问
InterlockedIncrement(&pthis->m_lRunThreadNums);
//从队列里取任务
while (!pthis->m_qItask.empty())
{
//添加互斥量解决线程并发
WaitForSingleObject(pthis->M_hMutex,INFINITE);
//上面是有阻塞的,所以需要判空
if (pthis->m_qItask.empty())
{
ReleaseMutex(pthis->M_hMutex);
break;
}
pItask = pthis->m_qItask.front();//不允许多个线程同时取任务
pthis->m_qItask.pop();
ReleaseMutex(pthis->M_hMutex);
//执行任务
pItask->Run();
//一直投递任务 所以需要在任务完成后删除任务
delete pItask;
pItask = NULL;
}
//pthis->m_lRunThreadNums--;
//解决线程并发问题,不允许多跟线程同时-- 原子访问
InterlockedDecrement(&pthis->m_lRunThreadNums);
}
return 0;
}
void MyThreadPool::DestroyThreadPool()
{
m_bFlagThread = false;
//检查线程是否退出,如果没有退出则强制杀死
//std::list<HANDLE>::iterator ite = m_lstThread.begin();
auto ite = m_lstThread.begin();
while(ite != m_lstThread.end())
{
if (WAIT_TIMEOUT == WaitForSingleObject(*ite,100))
{
TerminateThread(*ite,-1);
}
CloseHandle(*ite);
*ite = NULL;
ite++;
}
//释放信号量
if(m_hSemaphore)
{
CloseHandle(m_hSemaphore);
m_hSemaphore = NULL;
}
//删除有些投递没完成的任务
Itask *pItask = NULL;
while (!m_qItask.empty())
{
pItask = m_qItask.front();
m_qItask.pop();
delete pItask;
pItask = NULL;
}
if (M_hMutex)
{
CloseHandle(M_hMutex);
M_hMutex = NULL;
}
}
main.cpp
#include <QCoreApplication>
#include <MyThreadPool.h>
#include <iostream>
using namespace std;
class AddItask : public Itask
{
public:
AddItask(int a,int b)
{
m_a = a;
m_b = b;
}
~AddItask()
{}
public:
virtual void Run()
{
cout<<m_a<<"+"<<m_b<<"="<<m_a+m_b<<endl;
}
private:
int m_a;
int m_b;
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//创建线程池
MyThreadPool mythreadpool;
mythreadpool.CreateThreadPool(1,1000);
//向线程池投递任务
for(int i = 0; i < 1000000; i++)
{
Itask *pItask = new AddItask(i,i);
mythreadpool.Push(pItask);
}
return a.exec();
}