【转】一个windows线程池实现
#ifndef _ThreadPool_H_
#define _ThreadPool_H_
#pragma warning(disable: 4530)
#pragma warning(disable: 4786)
#include <cassert>
#include <vector>
#include <queue>
#include <windows.h>
using namespace std;
class ThreadJob //工作基类
{
public:
//供线程池调用的虚函数
virtual void DoJob(void *pPara) = ;
};
class ThreadPool
{
public:
//dwNum 线程池规模
ThreadPool(DWORD dwNum = ) : _lThreadNum(), _lRunningNum()
{
InitializeCriticalSection(&_csThreadVector);
InitializeCriticalSection(&_csWorkQueue);
_EventComplete = CreateEvent(, false, false, NULL);
_EventEnd = CreateEvent(, true, false, NULL);
_SemaphoreCall = CreateSemaphore(, , 0x7FFFFFFF, NULL);
_SemaphoreDel = CreateSemaphore(, , 0x7FFFFFFF, NULL);
assert(_SemaphoreCall != INVALID_HANDLE_VALUE);
assert(_EventComplete != INVALID_HANDLE_VALUE);
assert(_EventEnd != INVALID_HANDLE_VALUE);
assert(_SemaphoreDel != INVALID_HANDLE_VALUE);
AdjustSize(dwNum <= ? : dwNum);
}
~ThreadPool()
{
DeleteCriticalSection(&_csWorkQueue);
CloseHandle(_EventEnd);
CloseHandle(_EventComplete);
CloseHandle(_SemaphoreCall);
CloseHandle(_SemaphoreDel);
vector<ThreadItem*>::iterator iter;
for(iter = _ThreadVector.begin(); iter != _ThreadVector.end(); iter++)
{
if(*iter)
delete *iter;
}
DeleteCriticalSection(&_csThreadVector);
}
//调整线程池规模
int AdjustSize(int iNum)
{
if(iNum > )
{
ThreadItem *pNew;
EnterCriticalSection(&_csThreadVector);
for(int _i=; _i<iNum; _i++)
{
_ThreadVector.push_back(pNew = new ThreadItem(this));
assert(pNew);
pNew->_Handle = CreateThread(NULL, , DefaultJobProc, pNew, , NULL);
// set priority
SetThreadPriority(pNew->_Handle, THREAD_PRIORITY_BELOW_NORMAL);
assert(pNew->_Handle);
}
LeaveCriticalSection(&_csThreadVector);
}
else
{
iNum *= -;
ReleaseSemaphore(_SemaphoreDel, iNum > _lThreadNum ? _lThreadNum : iNum, NULL);
}
return (int)_lThreadNum;
}
//调用线程池
void Call(void (*pFunc)(void *), void *pPara = NULL)
{
assert(pFunc);
EnterCriticalSection(&_csWorkQueue);
_JobQueue.push(new JobItem(pFunc, pPara));
LeaveCriticalSection(&_csWorkQueue);
ReleaseSemaphore(_SemaphoreCall, , NULL);
}
//调用线程池
inline void Call(ThreadJob * p, void *pPara = NULL)
{
Call(CallProc, new CallProcPara(p, pPara));
}
//结束线程池, 并同步等待
bool EndAndWait(DWORD dwWaitTime = INFINITE)
{
SetEvent(_EventEnd);
return WaitForSingleObject(_EventComplete, dwWaitTime) == WAIT_OBJECT_0;
}
//结束线程池
inline void End()
{
SetEvent(_EventEnd);
}
inline DWORD Size()
{
return (DWORD)_lThreadNum;
}
inline DWORD GetRunningSize()
{
return (DWORD)_lRunningNum;
}
bool IsRunning()
{
return _lRunningNum > ;
}
protected:
//工作线程
static DWORD WINAPI DefaultJobProc(LPVOID lpParameter = NULL)
{
ThreadItem *pThread = static_cast<ThreadItem*>(lpParameter);
assert(pThread);
ThreadPool *pThreadPoolObj = pThread->_pThis;
assert(pThreadPoolObj);
InterlockedIncrement(&pThreadPoolObj->_lThreadNum);
HANDLE hWaitHandle[];
hWaitHandle[] = pThreadPoolObj->_SemaphoreCall;
hWaitHandle[] = pThreadPoolObj->_SemaphoreDel;
hWaitHandle[] = pThreadPoolObj->_EventEnd;
JobItem *pJob;
bool fHasJob;
for(;;)
{
DWORD wr = WaitForMultipleObjects(, hWaitHandle, false, INFINITE);
//响应删除线程信号
if(wr == WAIT_OBJECT_0 + )
break;
//从队列里取得用户作业
EnterCriticalSection(&pThreadPoolObj->_csWorkQueue);
if(fHasJob = !pThreadPoolObj->_JobQueue.empty())
{
pJob = pThreadPoolObj->_JobQueue.front();
pThreadPoolObj->_JobQueue.pop();
assert(pJob);
}
LeaveCriticalSection(&pThreadPoolObj->_csWorkQueue);
//受到结束线程信号 确定是否结束线程(结束线程信号 && 是否还有工作)
if(wr == WAIT_OBJECT_0 + && !fHasJob)
break;
if(fHasJob && pJob)
{
InterlockedIncrement(&pThreadPoolObj->_lRunningNum);
pThread->_dwLastBeginTime = GetTickCount();
pThread->_dwCount++;
pThread->_fIsRunning = true;
pJob->_pFunc(pJob->_pPara); //运行用户作业
delete pJob;
pThread->_fIsRunning = false;
InterlockedDecrement(&pThreadPoolObj->_lRunningNum);
}
}
//删除自身结构
EnterCriticalSection(&pThreadPoolObj->_csThreadVector);
pThreadPoolObj->_ThreadVector.erase(find(pThreadPoolObj->_ThreadVector.begin(), pThreadPoolObj->_ThreadVector.end(), pThread));
LeaveCriticalSection(&pThreadPoolObj->_csThreadVector);
delete pThread;
InterlockedDecrement(&pThreadPoolObj->_lThreadNum);
if(!pThreadPoolObj->_lThreadNum) //所有线程结束
SetEvent(pThreadPoolObj->_EventComplete);
return ;
}
//调用用户对象虚函数
static void CallProc(void *pPara)
{
CallProcPara *cp = static_cast<CallProcPara *>(pPara);
assert(cp);
if(cp)
{
cp->_pObj->DoJob(cp->_pPara);
delete cp;
}
}
//用户对象结构
struct CallProcPara
{
ThreadJob* _pObj;//用户对象
void *_pPara;//用户参数
CallProcPara(ThreadJob* p, void *pPara) : _pObj(p), _pPara(pPara) { };
};
//用户函数结构
struct JobItem
{
void (*_pFunc)(void *);//函数
void *_pPara; //参数
JobItem(void (*pFunc)(void *) = NULL, void *pPara = NULL) : _pFunc(pFunc), _pPara(pPara) { };
};
//线程池中的线程结构
struct ThreadItem
{
HANDLE _Handle; //线程句柄
ThreadPool *_pThis; //线程池的指针
DWORD _dwLastBeginTime; //最后一次运行开始时间
DWORD _dwCount; //运行次数
bool _fIsRunning;
ThreadItem(ThreadPool *pthis) : _pThis(pthis), _Handle(NULL), _dwLastBeginTime(), _dwCount(), _fIsRunning(false) { };
~ThreadItem()
{
if(_Handle)
{
CloseHandle(_Handle);
_Handle = NULL;
}
}
};
std::queue<JobItem *> _JobQueue; //工作队列
std::vector<ThreadItem *> _ThreadVector; //线程数据
CRITICAL_SECTION _csThreadVector, _csWorkQueue; //工作队列临界, 线程数据临界
HANDLE _EventEnd, _EventComplete, _SemaphoreCall, _SemaphoreDel;//结束通知, 完成事件, 工作信号, 删除线程信号
long _lThreadNum, _lRunningNum; //线程数, 运行的线程数
};
#endif //_ThreadPool_H_
转载自 http://blog.csdn.net/pjchen/archive/2004/11/06/170606.aspx
//...
}
ThreadPool tp;
for(i=0; i<100; i++)
tp.Call(threadfunc);
ThreadPool tp(20);//20为初始线程池规模
tp.Call(threadfunc, lpPara);
【转】一个windows线程池实现的更多相关文章
- 第11章 Windows线程池(2)_Win2008及以上的新线程池
11.2 Win2008以上的新线程池 (1)传统线程池的优缺点: ①传统Windows线程池调用简单,使用方便(有时只需调用一个API即可) ②这种简单也带来负面问题,如接口过于简单,无法更多去控制 ...
- 第11章 Windows线程池(1)_传统的Windows线程池
第11章 Windows线程池 11.1 传统的Windows线程池及API (1)线程池中的几种底层线程 ①可变数量的长任务线程:WT_EXECUTELONGFUNCTION ②Timer线程:调用 ...
- windows线程池四种情形(win核心读书笔记)
windows线程池四种情形(win核心读书笔记) Mircosoft从Windows2000引入线程池API,并在Vista后对线程池重新构架,引入新的线程池API.以下所有线程池函数均适用于Vis ...
- Windows核心编程:第11章 Windows线程池
Github https://github.com/gongluck/Windows-Core-Program.git //第11章 Windows线程池.cpp: 定义应用程序的入口点. // #i ...
- 《Windows核心编程系列》十一谈谈Windows线程池
Windows线程池 上一篇博文我们介绍了IO完成端口.得知IO完成端口可以非常智能的分派线程.但是IO完成端口仅对等待它的线程进行分派,创建和销毁线程的工作仍然需要我们自己来做. 我们自己也可以创建 ...
- 利用 Windows 线程池定制的 4 种方式完成任务(Windows 核心编程)
Windows 线程池 说起底层的线程操作一般都不会陌生,Windows 提供了 CreateThread 函数来创建线程,为了同步线程的操作,Windows 提供了事件内核对象.互斥量内核对象.关键 ...
- 发一个可伸缩线程池大小的python线程池。已通过测试。
发一个可伸缩线程池大小的线程池. 当任务不多时候,不开那么多线程,当任务多的时候开更多线程.当长时间没任务时候,将线程数量减小到一定数量. java的Threadpoolexcutor可以这样,py的 ...
- 第11章 Windows线程池(3)_私有的线程池
11.3 私有的线程池 11.3.1 创建和销毁私有的线程池 (1)进程默认线程池 当调用CreateThreadpoolwork.CreateThreadpoolTimer.CreateThread ...
- 一个python线程池的源码解析
python为了方便人们编程高度封装了很多东西,比如进程里的进程池,大大方便了人们编程的效率,但是默认却没有线程池,本人前段时间整理出一个线程池,并进行了简单的解析和注释,本人水平有限,如有错误希望高 ...
随机推荐
- POJ 2299 Ultra-QuickSort (排序+数据离散化+求顺序数)
题意:给出一个序列,求至少需要用到多少次操作,才能将序列从小到大排序. 思路: 数据量很大,n<500000,所以用冒泡模拟是超时的. 接下来就想到了求顺序数,总共需要交换的次数为每个数后面有多 ...
- C# 在vs2010中打开vs2012的项目(转)
在vs2010中打开vs2012的项目 今天在自己的电脑上装了vs2010然后要打开之前在vs2012上创建的sln文件 被提示-- 无法打开在新版本上创建的sln--解决方案--文件 其实vs201 ...
- POJ 2240 Arbitrage(floyd)
http://poj.org/problem?id=2240 题意 : 好吧,又是一个换钱的题:套利是利用货币汇率的差异进行的货币转换,例如用1美元购买0.5英镑,1英镑可以购买10法郎,一法郎可以购 ...
- Android ListView点击失效
item中存在 ImageButton 等可以点击的组件,这会抢先获得ListView的焦点. 从而导致item点击失效
- ssh 公钥
以前做ssh key登录方式时都是用的root帐号,基本都是无往不利的,权限采用默认即可.今天实验中两台机器帐号都是nianzong,一个普通的帐号.按照如下步骤: A机器:ssh-keygen -t ...
- 深入理解JVM—Java 6 JVM参数配置说明
原文地址:http://yhjhappy234.blog.163.com/blog/static/316328322011119111014657/ 使用说明< xmlnamespace pre ...
- 从SQL Server中导入/导出Excel的基本方法(转)
从sql server中导入/导出 excel 的基本方法 /*=========== 导入/导出 excel 的基本方法 ===========*/ 从excel文档中,导入数据到sql数据库中,很 ...
- Apache 下SVN项目管理使用说明
Apache 下SVN项目管理使用说明 (1)Apaceh和SVN先要装好. (2)在apache的目录下找到httpd.conf文件,在最后一行增加如下配置 Include conf/svn.pro ...
- Hibernate逍遥游记-第12章 映射值类型集合-003映射List(<list-index>)
1. <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hi ...
- Android:储存方式之SharePreferences
使用SharedPreferences保存数据,其实质是采用了xml文件存放数据, 存储位置:/data/data/<package name>/shared_prefs 写入: publ ...