线程池:减少频繁创建和销毁线程造成的应用程序效率下降的问题。
编译器:VC2005
了解创建线程的两个函数:
第一个是Platform SDK: DLLs, Processes, and Threads 即 win32 SDK 平台的系统API函数
HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId);
参数1.安全属性 该线程是否可以被继承
参数2.虚拟地址空间 一个线程默认有1M的虚拟内存,一个进程能创建线程的数量由虚拟地址空间限制。
参数3.线程函数
参数4.参数
参数5.线程状态(线程优先级0-7) 挂起 就绪 执行
参数6.线程ID
虚拟地址内存的作用是对真实物理内存的保护,内存分配是应用程序先预定虚拟内存再映射到真实物理内存。
此函数的问题:使用CreateThread()+ 静态的CRT库(动态库时没有这个问题)可能由于使用了线面的方法,导致每个线程申请私有空间的结构,但是,在线程结束之前不会对结构体进行释放从而导致内存泄露。
第二个是Run-Time Library Reference 即c/c++运行时库函数
uintptr_t _beginthreadex(
void *security,
unsigned stack_size,
unsigned ( *start_address )( void * ),
void *arglist,
unsigned initflag,
unsigned *thrdaddr
);或者_beginthread()
参数和createthread的是一样的意思。
线程函数结束时,线程并没有被销毁,线程对象必须等到线程句柄被closehandle掉。
_beginthreadex()是对CreateThread()的封装,再调用CreateThread()之前为每个线程创建私有空间保存错误码等信息,在线程函数返回后,自动调用_endthreadex()/_endthread(),这两个方法会将函数中为每个线程的私有空间进行释放,从而避免内存泄露。
介绍一个函数 ::GetTickCount() 线程运行到此处的时间, 在任务的前后分别放一个,两个返回值之差就是完成任务的时间,可以检查线程池的效率。
线程池的设计:
一.傻瓜式线程池:创建一堆线程,从不退出、不休息。(造成CPU的严重浪费,甚至可能导致主机卡死)
二.要解决傻瓜式线程池的问题需要满足:
1.不需要频繁的创建和销毁线程。(创建一组线程不退出)
2.当线程不需要工作的时候,不能死循环浪费CPU时间。(当线程没任务时,将线程挂起)
3.当有任务需要线程池处理时,需要马上有线程开始工作。(发信号通知,需要线程间同步)
线程间同步的方法:互斥量(1对1)、临界区(1)、事件(1对不定量)、信号量(1对n),所以选择信号量合适。
#pragma once
#ifndef _INCLUDE_THREAD_POOL_H_
#define _INCLUDE_THREAD_POOL_H_
#include <list>
namespace THREAD_POOL
{
//任务基类
class ITask
{
public:
BOOL virtual DealTask()=0;
};
//线程池类
class CThreadPool
{
public:
CThreadPool();
~CThreadPool();
//初始化线程池的功能 和 关闭线程池的功能
BOOL InitThreadPool(int iMinThreadCount,int iMaxThreadCount,int iTaskCount);//任务数量
void ColseThreadPool();
//投递任务
BOOL PostTask(ITask* pTask);
//创建信号量
HANDLE m_Semaphore;
private:
//任务链表 用指针对象 而不是对象集合
std::list<ITask*> m_TaskList;
int m_iMinThreadCount;
int m_iMaxThreadCount;
//一共创建了多少线程
int m_iCreateThreadCount;
//正在工作的线程
int m_iWorkThreadCount;
//任务队列的容量
int m_iTaskCount;
//临界区 任务队列锁
CRITICAL_SECTION m_Section;
//线程函数
static unsigned int WINAPI ThreadProc(LPVOID LpParam);
//静态函数没有this指针
void ThreadProc();
ITask* GetTask()
{
//队列里有任务了 要发送信号
::EnterCriticalSection(&m_Section);
ITask* pTask = NULL;
std::list<ITask*>::iterator it = m_TaskList.begin();
//放入的任务取出后 再取时 it变为空的无效指针
//对it间接引用
if (it != m_TaskList.end())
{
//说明取到了任务
pTask = *it;
m_TaskList.pop_front();
}
//任务被取出 释放信号量
::LeaveCriticalSection(&m_Section);
return pTask;
}
};
}
#endif
using namespace THREAD_POOL;
CThreadPool::CThreadPool():m_Semaphore(NULL)
,m_iMinThreadCount(0)
,m_iMaxThreadCount(0)
,m_iCreateThreadCount(0)
,m_iWorkThreadCount(0)
,m_iTaskCount(0)
{
//要初始化值类成员
}
CThreadPool::~CThreadPool()
{
ColseThreadPool();
}
BOOL CThreadPool::InitThreadPool(int iMinThreadCount,int iMaxThreadCount,int iTaskCount)
{
//校验参数
if(iMinThreadCount>iMaxThreadCount||iMinThreadCount<0||iTaskCount<0)
{
return FALSE;
}
//创建信号量 多个线程共同操作信号量 要加临界区
::InitializeCriticalSection(&m_Section);
m_Semaphore = ::CreateSemaphore(NULL,0,iMaxThreadCount,NULL);
if (!m_Semaphore)
{
return FALSE;
}
//创建线程
for(int i=0;i<iMinThreadCount;i++)
{
::InterlockedIncrement((long*)&m_iCreateThreadCount);
HANDLE hThread = (HANDLE)::_beginthreadex(NULL,0,ThreadProc,this,0,NULL);
if (!hThread)
{
::InterlockedDecrement((long*)&m_iCreateThreadCount);
return FALSE;
}
}
//保存数据
m_iMinThreadCount = iMinThreadCount;
m_iMaxThreadCount = iMaxThreadCount;
m_iTaskCount = iTaskCount;
m_iWorkThreadCount = 0;
return TRUE;
}
void CThreadPool::ColseThreadPool()
{
//安全函数 要保证可以多次调用
if (m_Semaphore)
{
::CloseHandle(m_Semaphore);
m_Semaphore = NULL;
}
m_TaskList.clear();
//这个位置这样写的话会产生内存泄露 在任务管理器中进程中会神奇的发现 内存项一点点的增长
//很好玩
//下边是回收空间的代码
//std::list<ITask*> m_TaskList;
//std::list<ITask*>::iterator it = m_TaskList.begin();
//while (it!=m_TaskList.end())
//{
// delete *it++;
//}
m_iMinThreadCount = 0;
m_iMaxThreadCount = 0;
}
unsigned int WINAPI CThreadPool::ThreadProc(LPVOID LpParam)
{
CThreadPool*pThis = (CThreadPool*)LpParam;
pThis->ThreadProc();
return 1l;
}
void CThreadPool::ThreadProc()
{
while(1)
{
//等待信号
::WaitForSingleObject(m_Semaphore,INFINITE);//一直等
//等到工作后 要将创建线程 变为 工作线程
::InterlockedIncrement((long*)&m_iWorkThreadCount);
//要循环处理队列里的任务
ITask* pTask = NULL;
while((pTask = GetTask())!=NULL)
{
pTask->DealTask();
delete pTask;
}
//任务处理完 要将工作线程变回创建线程
::InterlockedDecrement((long*)&m_iWorkThreadCount);
}
//减少创建线程数量
::InterlockedDecrement((long*)&m_iCreateThreadCount);
}
//投递任务
BOOL CThreadPool::PostTask(ITask* pTask)
{
if (!pTask)
{
return FALSE;
}
::EnterCriticalSection(&m_Section);
//在临界区内 向任务队列添加任务
m_TaskList.push_back(pTask);
::LeaveCriticalSection(&m_Section);
//如果 创建的线程有没工作的 发送信号 让其工作
if (m_iCreateThreadCount > m_iWorkThreadCount)
{
::ReleaseSemaphore(m_Semaphore,1,NULL);
}
else
{
//如果创建的线程都工作了 需要创建新的线程
if(m_iCreateThreadCount < m_iMaxThreadCount)
{
::InterlockedIncrement((long*)&m_iCreateThreadCount);
HANDLE hThread = (HANDLE)::_beginthreadex(NULL,0,ThreadProc,this,0,NULL);
if (!hThread)
{
::InterlockedDecrement((long*)&m_iCreateThreadCount);
return FALSE;
}
//给新创建的线程发信号 开始工作
::ReleaseSemaphore(m_Semaphore,1,NULL);
}
}
//::InterlockedIncrement((long*)&m_iWorkThreadCount);
return TRUE;
}
可以通过下班的代码进行测试
//加法任务 继承任务基类
class CAddTask:public ITask
{
public:
CAddTask(int nOne,int nTwo):m_nOne(nOne),m_nTwo(nTwo)
{
}
BOOL DealTask()
{
cout<< m_nOne + m_nTwo <<endl;
return TRUE;
}
private:
int m_nOne;
int m_nTwo;
};
int main()
{
CThreadPool threadpool;
threadpool.InitThreadPool(2,10,1000);
//投递任务
//ITask* pTask = new CAddTask(1,1);
for (int i=0;i<100000000;i++)
{
threadpool.PostTask(new CAddTask(1,1));
}
//threadpool.PostTask(pTask);
//阻塞一下
while (1)
{
::Sleep(10);
}
return 0;
}
上面的代码可以进行改进:
任务队列只有一个,由于线程间的同步,同一时间只有一个线程能对队列进行操作,其他线程只能在等待,这样线程的工作效率不高。
所以,可以拆分资源,各线程间不打扰,也就最大可能的提高了线程的工作效率。
改进方法:1:自己建立任务队列(队列的循环数组实现),代码量会减少很多
2:会不会觉得这几行代码的锁太多了?加锁和解锁的过程太多会浪费时间,所以 将锁包含在任务队列里
队列和锁在下边,把前边的改一改换一换就好了。。。。。。。。。。。
//队列/
#pragma once
#ifndef THREAD_TASK_QUEUE_
#define THREAD_TASK_QUEUE_
#include <Windows.h>
#include "MyLock.h"
namespace TASK_QUEUE
{
//队列的数组实现
template<typename T,int MAX_SIZE = 1000>
class CQueue
{
public:
CQueue();
~CQueue();
//初始化任务队列
BOOL InitQueue(int taskcount);
//关闭任务队列
void UnInitQueue();
//放入一个任务到队列
BOOL push_queue(T* pNode);
//从队列中取出一个任务
BOOL pop_queue(T*& pNode);
private:
int m_iHead;//循环数组的头
int m_iEnd;//循环数组的尾
int m_iMaxlength;//循环数组的长度
T** m_TaskArr;//动态数组
BOOL m_run;
CMyLock m_oLock;
};
//构造
template<typename T,int MAX_SIZE>
CQueue<T,MAX_SIZE>::CQueue()
:m_TaskArr(NULL)
,m_iHead(0)
,m_iEnd(0)
,m_iMaxlength(0)
,m_run(FALSE)
{
}
//析构
template<typename T,int MAX_SIZE>
CQueue<T,MAX_SIZE>::~CQueue()
{
UnInitQueue();
}
//初始化队列
template<typename T,int MAX_SIZE>
BOOL CQueue<T,MAX_SIZE>::InitQueue(int taskcount)
{
int QueueCount=min(MAX_SIZE,taskcount+1);
//记录长度
m_iMaxlength = QueueCount;
//创建数组
m_TaskArr=new T*[m_iMaxlength];
//队列开启标记
m_run = TRUE;
return TRUE;
}
//回收
template<typename T,int MAX_SIZE>
void CQueue<T,MAX_SIZE>::UnInitQueue()
{
m_run = FALSE;
::Sleep(10);
for (int i = 0;i<m_iMaxlength;i++)
{
if (m_TaskArr[i])
{
delete m_TaskArr[i];
m_TaskArr[i] = NULL;
}
}
if (m_TaskArr)
{
delete[] m_TaskArr;
}
}
//入队
template<typename T,int MAX_SIZE>
BOOL CQueue<T,MAX_SIZE>::push_queue(T* pNode)
{
if (pNode == NULL)
{
return FALSE;
}
m_oLock.Lock();
int index = (m_iHead+1)%m_iMaxlength;
if (index == m_iEnd)
{
//队满
m_oLock.UnLock();
return FALSE;
}
m_TaskArr[m_iHead] = pNode;
m_iHead = (m_iHead+1)%m_iMaxlength;
m_oLock.UnLock();
return TRUE;
}
//出队
template<typename T,int MAX_SIZE>
BOOL CQueue<T,MAX_SIZE>::pop_queue(T*& pNode)
{
m_oLock.Lock();
//如果队是空的
if (m_iHead == m_iEnd)
{
return FALSE;
}
m_oLock.UnLock();
pNode = m_TaskArr[m_iEnd];
m_TaskArr[m_iEnd] = NULL;
m_iEnd = (m_iEnd+1)%m_iMaxlength;
m_oLock.UnLock();
return TRUE;
}
}
#endif
锁的封装/
#pragma once
#ifndef THREAD_TASK_LOCK_
#define THREAD_TASK_LOCK_
#include <Windows.h>
class CMyLock
{
public:
//构造中创建临界区
CMyLock()
{
::InitializeCriticalSection(&m_Section);
}
//加锁进入临界区
void Lock()
{
::EnterCriticalSection(&m_Section);
}
//解锁离开临界区
void UnLock()
{
::LeaveCriticalSection(&m_Section);
}
//析构中销毁临界区
~CMyLock()
{
::DeleteCriticalSection(&m_Section);
}
private:
CRITICAL_SECTION m_Section;
};
#endif
编译器:VC2005
了解创建线程的两个函数:
第一个是Platform SDK: DLLs, Processes, and Threads 即 win32 SDK 平台的系统API函数
HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId);
参数1.安全属性 该线程是否可以被继承
参数2.虚拟地址空间 一个线程默认有1M的虚拟内存,一个进程能创建线程的数量由虚拟地址空间限制。
参数3.线程函数
参数4.参数
参数5.线程状态(线程优先级0-7) 挂起 就绪 执行
参数6.线程ID
虚拟地址内存的作用是对真实物理内存的保护,内存分配是应用程序先预定虚拟内存再映射到真实物理内存。
此函数的问题:使用CreateThread()+ 静态的CRT库(动态库时没有这个问题)可能由于使用了线面的方法,导致每个线程申请私有空间的结构,但是,在线程结束之前不会对结构体进行释放从而导致内存泄露。
第二个是Run-Time Library Reference 即c/c++运行时库函数
uintptr_t _beginthreadex(
void *security,
unsigned stack_size,
unsigned ( *start_address )( void * ),
void *arglist,
unsigned initflag,
unsigned *thrdaddr
);或者_beginthread()
参数和createthread的是一样的意思。
线程函数结束时,线程并没有被销毁,线程对象必须等到线程句柄被closehandle掉。
_beginthreadex()是对CreateThread()的封装,再调用CreateThread()之前为每个线程创建私有空间保存错误码等信息,在线程函数返回后,自动调用_endthreadex()/_endthread(),这两个方法会将函数中为每个线程的私有空间进行释放,从而避免内存泄露。
介绍一个函数 ::GetTickCount() 线程运行到此处的时间, 在任务的前后分别放一个,两个返回值之差就是完成任务的时间,可以检查线程池的效率。
线程池的设计:
一.傻瓜式线程池:创建一堆线程,从不退出、不休息。(造成CPU的严重浪费,甚至可能导致主机卡死)
二.要解决傻瓜式线程池的问题需要满足:
1.不需要频繁的创建和销毁线程。(创建一组线程不退出)
2.当线程不需要工作的时候,不能死循环浪费CPU时间。(当线程没任务时,将线程挂起)
3.当有任务需要线程池处理时,需要马上有线程开始工作。(发信号通知,需要线程间同步)
线程间同步的方法:互斥量(1对1)、临界区(1)、事件(1对不定量)、信号量(1对n),所以选择信号量合适。
#pragma once
#ifndef _INCLUDE_THREAD_POOL_H_
#define _INCLUDE_THREAD_POOL_H_
#include <list>
namespace THREAD_POOL
{
//任务基类
class ITask
{
public:
BOOL virtual DealTask()=0;
};
//线程池类
class CThreadPool
{
public:
CThreadPool();
~CThreadPool();
//初始化线程池的功能 和 关闭线程池的功能
BOOL InitThreadPool(int iMinThreadCount,int iMaxThreadCount,int iTaskCount);//任务数量
void ColseThreadPool();
//投递任务
BOOL PostTask(ITask* pTask);
//创建信号量
HANDLE m_Semaphore;
private:
//任务链表 用指针对象 而不是对象集合
std::list<ITask*> m_TaskList;
int m_iMinThreadCount;
int m_iMaxThreadCount;
//一共创建了多少线程
int m_iCreateThreadCount;
//正在工作的线程
int m_iWorkThreadCount;
//任务队列的容量
int m_iTaskCount;
//临界区 任务队列锁
CRITICAL_SECTION m_Section;
//线程函数
static unsigned int WINAPI ThreadProc(LPVOID LpParam);
//静态函数没有this指针
void ThreadProc();
ITask* GetTask()
{
//队列里有任务了 要发送信号
::EnterCriticalSection(&m_Section);
ITask* pTask = NULL;
std::list<ITask*>::iterator it = m_TaskList.begin();
//放入的任务取出后 再取时 it变为空的无效指针
//对it间接引用
if (it != m_TaskList.end())
{
//说明取到了任务
pTask = *it;
m_TaskList.pop_front();
}
//任务被取出 释放信号量
::LeaveCriticalSection(&m_Section);
return pTask;
}
};
}
#endif
using namespace THREAD_POOL;
CThreadPool::CThreadPool():m_Semaphore(NULL)
,m_iMinThreadCount(0)
,m_iMaxThreadCount(0)
,m_iCreateThreadCount(0)
,m_iWorkThreadCount(0)
,m_iTaskCount(0)
{
//要初始化值类成员
}
CThreadPool::~CThreadPool()
{
ColseThreadPool();
}
BOOL CThreadPool::InitThreadPool(int iMinThreadCount,int iMaxThreadCount,int iTaskCount)
{
//校验参数
if(iMinThreadCount>iMaxThreadCount||iMinThreadCount<0||iTaskCount<0)
{
return FALSE;
}
//创建信号量 多个线程共同操作信号量 要加临界区
::InitializeCriticalSection(&m_Section);
m_Semaphore = ::CreateSemaphore(NULL,0,iMaxThreadCount,NULL);
if (!m_Semaphore)
{
return FALSE;
}
//创建线程
for(int i=0;i<iMinThreadCount;i++)
{
::InterlockedIncrement((long*)&m_iCreateThreadCount);
HANDLE hThread = (HANDLE)::_beginthreadex(NULL,0,ThreadProc,this,0,NULL);
if (!hThread)
{
::InterlockedDecrement((long*)&m_iCreateThreadCount);
return FALSE;
}
}
//保存数据
m_iMinThreadCount = iMinThreadCount;
m_iMaxThreadCount = iMaxThreadCount;
m_iTaskCount = iTaskCount;
m_iWorkThreadCount = 0;
return TRUE;
}
void CThreadPool::ColseThreadPool()
{
//安全函数 要保证可以多次调用
if (m_Semaphore)
{
::CloseHandle(m_Semaphore);
m_Semaphore = NULL;
}
m_TaskList.clear();
//这个位置这样写的话会产生内存泄露 在任务管理器中进程中会神奇的发现 内存项一点点的增长
//很好玩
//下边是回收空间的代码
//std::list<ITask*> m_TaskList;
//std::list<ITask*>::iterator it = m_TaskList.begin();
//while (it!=m_TaskList.end())
//{
// delete *it++;
//}
m_iMinThreadCount = 0;
m_iMaxThreadCount = 0;
}
unsigned int WINAPI CThreadPool::ThreadProc(LPVOID LpParam)
{
CThreadPool*pThis = (CThreadPool*)LpParam;
pThis->ThreadProc();
return 1l;
}
void CThreadPool::ThreadProc()
{
while(1)
{
//等待信号
::WaitForSingleObject(m_Semaphore,INFINITE);//一直等
//等到工作后 要将创建线程 变为 工作线程
::InterlockedIncrement((long*)&m_iWorkThreadCount);
//要循环处理队列里的任务
ITask* pTask = NULL;
while((pTask = GetTask())!=NULL)
{
pTask->DealTask();
delete pTask;
}
//任务处理完 要将工作线程变回创建线程
::InterlockedDecrement((long*)&m_iWorkThreadCount);
}
//减少创建线程数量
::InterlockedDecrement((long*)&m_iCreateThreadCount);
}
//投递任务
BOOL CThreadPool::PostTask(ITask* pTask)
{
if (!pTask)
{
return FALSE;
}
::EnterCriticalSection(&m_Section);
//在临界区内 向任务队列添加任务
m_TaskList.push_back(pTask);
::LeaveCriticalSection(&m_Section);
//如果 创建的线程有没工作的 发送信号 让其工作
if (m_iCreateThreadCount > m_iWorkThreadCount)
{
::ReleaseSemaphore(m_Semaphore,1,NULL);
}
else
{
//如果创建的线程都工作了 需要创建新的线程
if(m_iCreateThreadCount < m_iMaxThreadCount)
{
::InterlockedIncrement((long*)&m_iCreateThreadCount);
HANDLE hThread = (HANDLE)::_beginthreadex(NULL,0,ThreadProc,this,0,NULL);
if (!hThread)
{
::InterlockedDecrement((long*)&m_iCreateThreadCount);
return FALSE;
}
//给新创建的线程发信号 开始工作
::ReleaseSemaphore(m_Semaphore,1,NULL);
}
}
//::InterlockedIncrement((long*)&m_iWorkThreadCount);
return TRUE;
}
可以通过下班的代码进行测试
//加法任务 继承任务基类
class CAddTask:public ITask
{
public:
CAddTask(int nOne,int nTwo):m_nOne(nOne),m_nTwo(nTwo)
{
}
BOOL DealTask()
{
cout<< m_nOne + m_nTwo <<endl;
return TRUE;
}
private:
int m_nOne;
int m_nTwo;
};
int main()
{
CThreadPool threadpool;
threadpool.InitThreadPool(2,10,1000);
//投递任务
//ITask* pTask = new CAddTask(1,1);
for (int i=0;i<100000000;i++)
{
threadpool.PostTask(new CAddTask(1,1));
}
//threadpool.PostTask(pTask);
//阻塞一下
while (1)
{
::Sleep(10);
}
return 0;
}
上面的代码可以进行改进:
任务队列只有一个,由于线程间的同步,同一时间只有一个线程能对队列进行操作,其他线程只能在等待,这样线程的工作效率不高。
所以,可以拆分资源,各线程间不打扰,也就最大可能的提高了线程的工作效率。
改进方法:1:自己建立任务队列(队列的循环数组实现),代码量会减少很多
2:会不会觉得这几行代码的锁太多了?加锁和解锁的过程太多会浪费时间,所以 将锁包含在任务队列里
队列和锁在下边,把前边的改一改换一换就好了。。。。。。。。。。。
//队列/
#pragma once
#ifndef THREAD_TASK_QUEUE_
#define THREAD_TASK_QUEUE_
#include <Windows.h>
#include "MyLock.h"
namespace TASK_QUEUE
{
//队列的数组实现
template<typename T,int MAX_SIZE = 1000>
class CQueue
{
public:
CQueue();
~CQueue();
//初始化任务队列
BOOL InitQueue(int taskcount);
//关闭任务队列
void UnInitQueue();
//放入一个任务到队列
BOOL push_queue(T* pNode);
//从队列中取出一个任务
BOOL pop_queue(T*& pNode);
private:
int m_iHead;//循环数组的头
int m_iEnd;//循环数组的尾
int m_iMaxlength;//循环数组的长度
T** m_TaskArr;//动态数组
BOOL m_run;
CMyLock m_oLock;
};
//构造
template<typename T,int MAX_SIZE>
CQueue<T,MAX_SIZE>::CQueue()
:m_TaskArr(NULL)
,m_iHead(0)
,m_iEnd(0)
,m_iMaxlength(0)
,m_run(FALSE)
{
}
//析构
template<typename T,int MAX_SIZE>
CQueue<T,MAX_SIZE>::~CQueue()
{
UnInitQueue();
}
//初始化队列
template<typename T,int MAX_SIZE>
BOOL CQueue<T,MAX_SIZE>::InitQueue(int taskcount)
{
int QueueCount=min(MAX_SIZE,taskcount+1);
//记录长度
m_iMaxlength = QueueCount;
//创建数组
m_TaskArr=new T*[m_iMaxlength];
//队列开启标记
m_run = TRUE;
return TRUE;
}
//回收
template<typename T,int MAX_SIZE>
void CQueue<T,MAX_SIZE>::UnInitQueue()
{
m_run = FALSE;
::Sleep(10);
for (int i = 0;i<m_iMaxlength;i++)
{
if (m_TaskArr[i])
{
delete m_TaskArr[i];
m_TaskArr[i] = NULL;
}
}
if (m_TaskArr)
{
delete[] m_TaskArr;
}
}
//入队
template<typename T,int MAX_SIZE>
BOOL CQueue<T,MAX_SIZE>::push_queue(T* pNode)
{
if (pNode == NULL)
{
return FALSE;
}
m_oLock.Lock();
int index = (m_iHead+1)%m_iMaxlength;
if (index == m_iEnd)
{
//队满
m_oLock.UnLock();
return FALSE;
}
m_TaskArr[m_iHead] = pNode;
m_iHead = (m_iHead+1)%m_iMaxlength;
m_oLock.UnLock();
return TRUE;
}
//出队
template<typename T,int MAX_SIZE>
BOOL CQueue<T,MAX_SIZE>::pop_queue(T*& pNode)
{
m_oLock.Lock();
//如果队是空的
if (m_iHead == m_iEnd)
{
return FALSE;
}
m_oLock.UnLock();
pNode = m_TaskArr[m_iEnd];
m_TaskArr[m_iEnd] = NULL;
m_iEnd = (m_iEnd+1)%m_iMaxlength;
m_oLock.UnLock();
return TRUE;
}
}
#endif
锁的封装/
#pragma once
#ifndef THREAD_TASK_LOCK_
#define THREAD_TASK_LOCK_
#include <Windows.h>
class CMyLock
{
public:
//构造中创建临界区
CMyLock()
{
::InitializeCriticalSection(&m_Section);
}
//加锁进入临界区
void Lock()
{
::EnterCriticalSection(&m_Section);
}
//解锁离开临界区
void UnLock()
{
::LeaveCriticalSection(&m_Section);
}
//析构中销毁临界区
~CMyLock()
{
::DeleteCriticalSection(&m_Section);
}
private:
CRITICAL_SECTION m_Section;
};
#endif