利用C++实现了一个简易的线程池模型(基于Win32 SDK),方便使用多线程处理任务。共包含Thread.h、Thread.cpp、ThreadPool.h、ThreadPool.cpp四个源文件。功能相对简单,尚待完善。

Thread.h

 // Thread.h: interface for the CThread class.
//
////////////////////////////////////////////////////////////////////// #if !defined(AFX_THREAD_H__9BC45342_F764_4104_B614_1CC8A1964171__INCLUDED_)
#define AFX_THREAD_H__9BC45342_F764_4104_B614_1CC8A1964171__INCLUDED_ #if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000 class CThread
{
public:
CThread();
virtual ~CThread(); public:
BOOL IsBusy();
void Terminate();
DWORD GetThreadId() const;
void Run(LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter); protected:
void _SetBusy(BOOL bBusy); private:
void __Proc();
static DWORD WINAPI __ThreadProc(LPVOID lpParameter); protected:
LPTHREAD_START_ROUTINE m_pThreadProc;
LPVOID m_pParameter; BOOL m_bBusy;
CRITICAL_SECTION m_csBusy; HANDLE m_hEventWait;
HANDLE m_hEventExit; HANDLE m_hThread;
DWORD m_dwThreadId;
}; #endif // !defined(AFX_THREAD_H__9BC45342_F764_4104_B614_1CC8A1964171__INCLUDED_)

Thread.cpp

 // Thread.cpp: implementation of the CThread class.
//
////////////////////////////////////////////////////////////////////// #include "StdAfx.h"
#include "Thread.h" CThread::CThread()
: m_pThreadProc()
, m_pParameter()
, m_bBusy()
, m_hThread()
{
m_hEventWait = CreateEvent(, TRUE, FALSE, NULL);
m_hEventExit = CreateEvent(, TRUE, FALSE, NULL);
InitializeCriticalSection(&m_csBusy);
m_hThread = CreateThread(, , __ThreadProc, this, , &m_dwThreadId);
} CThread::~CThread()
{
Terminate();
WaitForSingleObject(m_hThread, INFINITE);
CloseHandle(m_hThread);
DeleteCriticalSection(&m_csBusy);
CloseHandle(m_hEventWait);
CloseHandle(m_hEventExit);
} void CThread::Terminate()
{
SetEvent(m_hEventExit);
} BOOL CThread::IsBusy()
{
EnterCriticalSection(&m_csBusy);
BOOL bRet = m_bBusy;
LeaveCriticalSection(&m_csBusy);
return bRet;
} void CThread::_SetBusy(BOOL bBusy)
{
EnterCriticalSection(&m_csBusy);
m_bBusy = bBusy;
LeaveCriticalSection(&m_csBusy);
} DWORD CThread::GetThreadId() const
{
return m_dwThreadId;
} void CThread::Run(LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter)
{
if (!IsBusy() && lpStartAddress)
{
_SetBusy(TRUE);
m_pThreadProc = lpStartAddress;
m_pParameter = lpParameter;
SetEvent(m_hEventWait);
}
} DWORD WINAPI CThread::__ThreadProc(LPVOID lpParameter)
{
CThread* pThis = (CThread*)lpParameter;
pThis->__Proc(); return ;
} void CThread::__Proc()
{
for (;;)
{
if (!m_pThreadProc)
{
HANDLE hEvents[] = {m_hEventExit, m_hEventWait};
DWORD dwRet = WaitForMultipleObjects(, hEvents, FALSE, INFINITE);
if (dwRet - WAIT_OBJECT_0 == ) break;
}
m_pThreadProc(m_pParameter);
m_pThreadProc = NULL;
m_pParameter = NULL;
ResetEvent(m_hEventWait);
_SetBusy(FALSE);
}
}

ThreadPool.h

 // ThreadPool.h: interface for the CThreadPool class.
//
////////////////////////////////////////////////////////////////////// #if !defined(AFX_THREADPOOL_H__E24F5439_D623_4511_A874_40CC9417DDEE__INCLUDED_)
#define AFX_THREADPOOL_H__E24F5439_D623_4511_A874_40CC9417DDEE__INCLUDED_ #if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000 #pragma warning(push)
#pragma warning(disable: 4786) #include <queue>
#include <vector>
#include <utility> #pragma warning(pop) class CThread;
class CThreadPool
{
public:
CThreadPool(size_t nMaxCount);
virtual ~CThreadPool(); public:
BOOL IsBusy();
BOOL Wait(DWORD dwMilliseconds);
void Run(LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter); private:
void __Proc();
static DWORD WINAPI __ThreadProc(LPVOID lpParameter); protected:
HANDLE m_hThread;
HANDLE m_hEventExit; CRITICAL_SECTION m_csFunc; std::vector<CThread*> m_vThreads;
std::queue< std::pair<LPTHREAD_START_ROUTINE, LPVOID> > m_qFuncs;
}; #endif // !defined(AFX_THREADPOOL_H__E24F5439_D623_4511_A874_40CC9417DDEE__INCLUDED_)

ThreadPool.cpp

 // ThreadPool.cpp: implementation of the CThreadPool class.
//
////////////////////////////////////////////////////////////////////// #include "StdAfx.h"
#include "Thread.h"
#include <algorithm>
#include "ThreadPool.h" CThreadPool::CThreadPool(size_t nMaxCount)
{
for (size_t i(); i < nMaxCount; ++i)
{
m_vThreads.push_back(new CThread);
}
InitializeCriticalSection(&m_csFunc);
m_hEventExit = CreateEvent(NULL, TRUE, FALSE, NULL);
m_hThread = CreateThread(, , __ThreadProc, this, , );
} CThreadPool::~CThreadPool()
{
SetEvent(m_hEventExit);
WaitForSingleObject(m_hThread, INFINITE);
CloseHandle(m_hThread);
for (std::vector<CThread*>::iterator i(m_vThreads.begin())
; i != m_vThreads.end(); ++i)
{
delete *i;
}
m_vThreads.clear();
DeleteCriticalSection(&m_csFunc);
} DWORD WINAPI CThreadPool::__ThreadProc(LPVOID lpParameter)
{
CThreadPool* pThis = (CThreadPool*)lpParameter;
pThis->__Proc(); return ;
} void CThreadPool::__Proc()
{
for (;WaitForSingleObject(m_hEventExit, ) != WAIT_OBJECT_0;)
{
EnterCriticalSection(&m_csFunc);
if (!m_qFuncs.empty())
{
for (std::vector<CThread*>::iterator i(m_vThreads.begin())
; i != m_vThreads.end(); ++i)
{
if (!(*i)->IsBusy() && !m_qFuncs.empty())
{
std::pair<LPTHREAD_START_ROUTINE, LPVOID>& pFunc = m_qFuncs.front();
(*i)->Run(pFunc.first, pFunc.second);
m_qFuncs.pop();
}
}
}
LeaveCriticalSection(&m_csFunc);
}
} void CThreadPool::Run(LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter)
{
EnterCriticalSection(&m_csFunc);
std::pair<LPTHREAD_START_ROUTINE, LPVOID> pFunc(std::make_pair(lpStartAddress, lpParameter));
m_qFuncs.push(pFunc);
LeaveCriticalSection(&m_csFunc);
} BOOL CThreadPool::IsBusy()
{
BOOL bRet(FALSE);
EnterCriticalSection(&m_csFunc);
if (m_qFuncs.empty())
{
for (std::vector<CThread*>::iterator i(m_vThreads.begin())
; i != m_vThreads.end(); ++i)
{
if ((*i)->IsBusy())
{
bRet = TRUE;
break;
}
}
}
else bRet = TRUE;
LeaveCriticalSection(&m_csFunc);
return bRet;
} BOOL CThreadPool::Wait(DWORD dwMilliseconds)
{
DWORD dwTick = GetTickCount();
for (;IsBusy();)
{
Sleep();
if (GetTickCount() - dwTick > dwMilliseconds)
{
break;
}
}
return !IsBusy();
}

使用示例:

 // Test.cpp : Defines the entry point for the console application.
// #include "StdAfx.h"
#include "ThreadPool.h" CRITICAL_SECTION cs; using namespace std; DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
EnterCriticalSection(&cs);
cout << LPCSTR(lpParameter) << endl;
LeaveCriticalSection(&cs);
return ;
} int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
InitializeCriticalSection(&cs); CThreadPool *pThrealPool = new CThreadPool();
pThrealPool->Run(ThreadProc, "");
pThrealPool->Run(ThreadProc, "");
pThrealPool->Run(ThreadProc, "");
pThrealPool->Run(ThreadProc, "");
pThrealPool->Run(ThreadProc, "");
pThrealPool->Run(ThreadProc, "");
pThrealPool->Run(ThreadProc, ""); pThrealPool->Wait(INFINIE);
delete pThrealPool; DeleteCriticalSection(&cs); return nRetCode;
}

运行结果:

源代码下载:http://t.cn/RvnJe9S

基于Win32 SDK实现的一个简易线程池的更多相关文章

  1. Linux下简易线程池

    线程池简介 线程池是可以用来在后台执行多个任务的线程集合. 这使主线程可以自由地异步执行其他任务.线程池通常用于服务器应用程序. 每个传入请求都将分配给线程池中的一个线程,因此可以异步处理请求,而不会 ...

  2. 基于requests模块的cookie,session和线程池爬取

    目录 基于requests模块的cookie,session和线程池爬取 基于requests模块的cookie操作 基于requests模块的代理操作 基于multiprocessing.dummy ...

  3. 发一个可伸缩线程池大小的python线程池。已通过测试。

    发一个可伸缩线程池大小的线程池. 当任务不多时候,不开那么多线程,当任务多的时候开更多线程.当长时间没任务时候,将线程数量减小到一定数量. java的Threadpoolexcutor可以这样,py的 ...

  4. 基于 getter 和 setter 撸一个简易的MVVM

    Angular 和 Vue 在对Angular的学习中,了解到AngularJS 的两个主要缺点: 对于每一次界面时间,Ajax 或者 timeout,都会进行一个脏检查,而每一次脏检查又会在内部循环 ...

  5. 【转】一个windows线程池实现

    #ifndef _ThreadPool_H_ #define _ThreadPool_H_ #pragma warning(disable: 4530) #pragma warning(disable ...

  6. 用java自制简易线程池(不依赖concurrent包)

    很久之前人们为了继续享用并行化带来的好处而不想使用进程,于是创造出了比进程更轻量级的线程.以linux为例,创建一个进程需要申请新的自己的内存空间,从父进程拷贝一些数据,所以开销是比较大的,线程(或称 ...

  7. 简易线程池Thread Pool

    1. 基本思路 写了个简易的线程池,基本的思路是: 有1个调度线程,负责维护WorkItem队列.管理线程(是否要增加工作线程).调度(把工作项赋给工作线程)等 线程数量随WorkItem的量动态调整 ...

  8. 一个python线程池的源码解析

    python为了方便人们编程高度封装了很多东西,比如进程里的进程池,大大方便了人们编程的效率,但是默认却没有线程池,本人前段时间整理出一个线程池,并进行了简单的解析和注释,本人水平有限,如有错误希望高 ...

  9. 一个自定义线程池的小Demo

    在项目中如果是web请求时候,IIS会自动分配一个线程来进行处理,如果很多个应用程序共享公用一个IIS的时候,线程分配可能会出现一个问题(当然也是我的需求造成的) 之前在做项目的时候,有一个需求,就是 ...

随机推荐

  1. html5权威指南:定制input元素

    第十三章:定制Inpur元素,http://www.cnblogs.com/polk6/p/5417921.html#Menu3-New input标签最全面的type属性:http://blog.s ...

  2. C socket指南

    1.介绍 Socket 编程让你沮丧吗?从man pages中很难得到有用的信息吗?你想跟上时代去编Internet相关的程序,但是为你在调用 connect() 前的bind() 的结构而不知所措? ...

  3. js函数的一些技巧

    1 函数的引用可以直接通过函数名来调用 bind: function (fn, scope) { return function () { return fn.apply(scope, argumen ...

  4. C#连接sqlserver数据库

    // 混合登录 写法1:Data Source=myServerAddress;Initial Catalog=myDataBase;User Id=myUsername;Password=myPas ...

  5. wep密钥的长度

    理论上,WEP可以搭配任意长度的密钥,因为RC4并未要求非得使用特定长度的密钥. 不过,大多数产品均支持一种或两种长度的密钥.唯一出现在标准中的密钥长度时64位的WEP种子(seed),其中40位是两 ...

  6. setsockopt、getsockopt详细介绍(转)

    本文只讲解socket编程中的 setsockopt.getsockopt两个函数.关于其它函数的介绍可以参考下面链接:http://blog.sina.com.cn/s/blog_a459dcf50 ...

  7. SSL读书笔记

    摘要: 第一次写博客,为读书笔记,参考书目如下: <HTTP权威指南> <图解HTTP> <大型分布式网站架构设计与实践> 作者:陈康贤 一. HTTP+SSL=H ...

  8. The message filter indicated that the application is busy. (Exception from HRESULT: 0x8001010A (RPC_E_SERVERCALL_RETRYLATER))

    消息筛选器显示应用程序正在使用中. ((错误来自 HRESULT:0x8001010A (RPC_E_SERVERCALL_RETRYLATER)) 在对Word文档进行合并或者其他操作的时候,如果数 ...

  9. aspose 解决插入html后字体问题

    /// <summary> /// 添加html /// </summary> /// <param name="strText"></p ...

  10. 【Machine Learning in Action --4】朴素贝叶斯从个人广告中获取区域倾向

    背景:广告商往往想知道关于一个人的一些特定人口统计信息,以便能更好地定向推销广告. 我们将分别从美国的两个城市中选取一些人,通过分析这些人发布的信息,来比较这两个城市的人们在广告用词上是否不同.如果结 ...