原文转自:http://www.cnblogs.com/lidabo/p/3328646.html

略有修改

Cthread类参见:http://www.cnblogs.com/tangxin-blog/p/4835211.html

CThreadPool.h

 #ifndef __MY_THREAD_POOL_H_
#define __MY_THREAD_POOL_H_ #include "CThread.h"
#include <set>
#include <list>
#include <windows.h>
using namespace std; class CThreadPool
{
public:
CThreadPool(void);
virtual ~CThreadPool(void);
// 初始化线程池,创建minThreads个线程
bool Initialize(unsigned int minThreadCnt,unsigned int maxThreadCnt,unsigned int maxTaskQueueLength);
bool AddTask( CRunnable *pRunnable, bool bRun = true);
void Terminate();
// 获取线程数量
unsigned int GetThreadCnt();
private:
// 从任务队列头中取出一个任务
CRunnable *GetTask();
// 执行任务线程
static unsigned int WINAPI StaticThreadFunc(void * arg);
private:
// 工作者类
class CWorker : public CThread
{
public:
CWorker(CThreadPool *pThreadPool,CRunnable *pFirstTask = NULL);
~CWorker();
void Run();
private:
CThreadPool * const m_pThreadPool;
CRunnable * const m_pFirstTask;
volatile bool m_bRun;
}; typedef std::set<CWorker *> ThreadPool;
typedef std::list<CRunnable *> Tasks;
typedef Tasks::iterator TasksItr;
typedef ThreadPool::iterator ThreadPoolItr; CRITICAL_SECTION m_csTasksLock;
CRITICAL_SECTION m_csThreadPoolLock; // 线程池
ThreadPool m_ThreadPool;
// 垃圾线程
ThreadPool m_TrashThread;
// 任务队列
Tasks m_Tasks;
// 是否在运行
volatile bool m_bRun;
// 能否插入任务
volatile bool m_bEnableInsertTask;
// 最小线程数
volatile unsigned int m_minThreads;
// 最大线程数
volatile unsigned int m_maxThreads;
// 最大挂起任务数量
volatile unsigned int m_maxPendingTasks;
}; #endif

CthreadPool.cpp

#include "CThreadPool.h"

CThreadPool::CWorker::CWorker(CThreadPool *pThreadPool,CRunnable *pFirstTask)
:m_pThreadPool(pThreadPool),m_pFirstTask(pFirstTask),m_bRun(true)
{ } CThreadPool::CWorker::~CWorker()
{
} void CThreadPool::CWorker::Run()
{
CRunnable * pTask = NULL;
while(m_bRun)
{
// 从线程池的任务队列中取出一个任务
pTask = m_pThreadPool->GetTask();
// 如果没有取到任务
if(NULL == pTask)
{
EnterCriticalSection(&(m_pThreadPool->m_csThreadPoolLock));
// 如果运转的线程数大于最小线程数,需要清除多余的线程
if(m_pThreadPool->GetThreadCnt() > m_pThreadPool->m_minThreads)
{
ThreadPoolItr itr = m_pThreadPool->m_ThreadPool.find(this);
if(itr != m_pThreadPool->m_ThreadPool.end())
{
m_pThreadPool->m_ThreadPool.erase(itr);
m_pThreadPool->m_TrashThread.insert(this);
}
m_bRun = false;
}
else
{
// 等待已经开始运行的线程结束
ThreadPoolItr itr = m_pThreadPool->m_TrashThread.begin();
while(itr != m_pThreadPool->m_TrashThread.end())
{
(*itr)->Join();
delete (*itr);
m_pThreadPool->m_TrashThread.erase(itr);
itr = m_pThreadPool->m_TrashThread.begin();
}
}
LeaveCriticalSection(&(m_pThreadPool->m_csThreadPoolLock));
continue;
}
else
{
pTask->Run();
pTask = NULL;
}
}
} CThreadPool::CThreadPool(void):m_bRun(false),m_bEnableInsertTask(false)
{
InitializeCriticalSection(&m_csTasksLock);
InitializeCriticalSection(&m_csThreadPoolLock);
} CThreadPool::~CThreadPool(void)
{
Terminate();
DeleteCriticalSection(&m_csTasksLock);
DeleteCriticalSection(&m_csThreadPoolLock);
} bool CThreadPool::Initialize(unsigned int minThreadCnt,unsigned int maxThreadCnt,unsigned int maxTaskQueueLength)
{
if(minThreadCnt == )
{
return false;
}
if(minThreadCnt > maxThreadCnt)
{
return false;
}
m_minThreads = minThreadCnt;
m_maxThreads = maxThreadCnt;
m_maxPendingTasks = maxTaskQueueLength;
unsigned int i = m_ThreadPool.size();
for(; i<minThreadCnt; i++)
{
//创建线程 minThreadCnt 个线程
CWorker * pWorker = new CWorker(this);
if(NULL == pWorker)
{
return false;
}
EnterCriticalSection(&m_csThreadPoolLock);
m_ThreadPool.insert(pWorker);
LeaveCriticalSection(&m_csThreadPoolLock);
pWorker->Start();
}
// 可以开始插入任务队列
m_bRun = true;
m_bEnableInsertTask = true;
return true;
} unsigned int CThreadPool::GetThreadCnt()
{
return m_ThreadPool.size();
} CRunnable * CThreadPool::GetTask()
{
CRunnable *Task = NULL;
EnterCriticalSection(&m_csTasksLock);
if(!m_Tasks.empty())
{
Task = m_Tasks.front();
m_Tasks.pop_front();
}
LeaveCriticalSection(&m_csTasksLock);
return Task;
} bool CThreadPool::AddTask( CRunnable *pRunnable, bool bRun /*= true*/ )
{
if(m_bEnableInsertTask == false)
{
return false;
}
if(NULL == pRunnable)
{
return false;
}
// 如果达到最大挂起任务数量,不再插入
if(m_Tasks.size() >= m_maxPendingTasks)
{
// 如果小于最大线程数
if(m_ThreadPool.size() < m_maxThreads)
{
CWorker * pWorker = new CWorker(this, pRunnable);
if(NULL == pWorker)
{
return false;
}
EnterCriticalSection(&m_csThreadPoolLock);
m_ThreadPool.insert(pWorker);
LeaveCriticalSection(&m_csThreadPoolLock);
pWorker->Start();
}
else
{
return false;
}
}
else
{
EnterCriticalSection(&m_csTasksLock);
m_Tasks.push_back(pRunnable);
LeaveCriticalSection(&m_csTasksLock);
}
return true;
} void CThreadPool::Terminate()
{
m_bEnableInsertTask = false;
while(m_Tasks.size() > )
{
Sleep();
}
m_bRun = false;
m_minThreads = ;
m_maxThreads = ;
m_maxPendingTasks = ;
while(m_ThreadPool.size() > )
{
Sleep();
}
EnterCriticalSection(&m_csThreadPoolLock);
ThreadPoolItr itr = m_TrashThread.begin();
while(itr != m_TrashThread.end())
{
(*itr)->Join();
delete (*itr);
m_TrashThread.erase(itr);
itr = m_TrashThread.begin();
}
LeaveCriticalSection(&m_csThreadPoolLock);
}

测试代码

#include <iostream>
#include <windows.h>
#include <time.h>
#include "CThread.h"
#include "CThreadPool.h"
using namespace std; class R : public CRunnable
{
public:
R(int t):m_nt(t)
{
}
~R()
{
cout<<"~R:"<<m_nt<<endl;
}
void Run()
{
Sleep(m_nt);
}
int m_nt;
}; int main()
{
int i,n = ,m;
time_t start = ,end = ;
R r();
/*
// 单线程
start = clock();
for(i=0;i < n;i++)
{
r.Run();
}
end = clock();
cout<<"单线程用时:"<<end - start<<endl;
*/
// 多线程
start = clock();
CThread *ths = NULL;
ths = new CThread[n];
for(i=;i < n;i++)
{
ths[i].SetRunnable(&r);
ths[i].Start();
}
for(i=;i < n;i++)
{
ths[i].Join();
}
delete[] ths;
end = clock();
cout<<"多线程用时:"<<end - start<<endl;
// 线程池
start = clock();
CThreadPool *threadPool = new CThreadPool();
if(threadPool->Initialize(,,) == false)
{
cout<<"Initialize failed"<<endl;
return -;
}
m = ;
for(int i=;i<n;i++)
{
if( !threadPool->AddTask(&r) )
{
m++;
}
}
threadPool->Terminate();
delete threadPool;
end = clock();
if(m!=)
{
cout<<m<<endl;
}
cout<<"线程池用时:"<<end - start<<endl;
system("pause");
return ;
}

注意:要合理设置最小线程数,最大线程数,最大挂起任务数量,以便达到最优性能。

转载:C++线程池的一个实现的更多相关文章

  1. [转载] Java线程池框架源码分析

    转载自http://www.linuxidc.com/Linux/2014-11/108791.htm 相关类Executor,Executors,AbstractExecutorService,Ex ...

  2. ThreadPoolExecutor线程池的一个面试题

    问题:现有一个线程池,参数corePoolSize = 5,maximumPoolSize = 10,BlockingQueue阻塞队列长度为5,此时有4个任务同时进来,问:线程池会创建几条线程? 如 ...

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

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

  4. Java并发编程:线程池的使用(转载)

    转载自:https://www.cnblogs.com/dolphin0520/p/3932921.html Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实 ...

  5. Java并发编程:线程池的使用(转载)

    文章出处:http://www.cnblogs.com/dolphin0520/p/3932921.html Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实 ...

  6. Java线程状态、线程start方法源码、多线程、Java线程池、如何停止一个线程

    下面将依次介绍: 1. 线程状态.Java线程状态和线程池状态 2. start方法源码 3. 什么是线程池? 4. 线程池的工作原理和使用线程池的好处 5. ThreadPoolExecutor中的 ...

  7. 深入了解java线程池(转载)

    出处:http://www.cnblogs.com/dolphin0520/ 本文归作者海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责 ...

  8. 分享一个自制的 .net线程池

    扯淡 由于项目需求,需要开发一些程序去爬取一些网站的信息,算是小爬虫程序吧.爬网页这东西是要经过网络传输,如果程序运行起来串行执行请求爬取,会很慢,我想没人会这样做.为了提高爬取效率,必须使用多线程并 ...

  9. asp.net core C#设计一个实用的线程池

    菜菜呀,我最近研究技术呢,发现线上一个任务程序线程数有点多呀 CEO,CTO,CFO于一身的CXO x总,你学编程呢? 菜菜 作为公司总负责人,我以后还要管理技术部门呢,怎么能不会技术呢 CEO,CT ...

随机推荐

  1. DP(优化) UVALive 6073 Math Magic

    /************************************************ * Author :Running_Time * Created Time :2015/10/28 ...

  2. POJ3057 Evacuation(二分图最大匹配)

    人作X部:把门按时间拆点,作Y部:如果某人能在某个时间到达某门则连边.就是个二分图最大匹配. 时间可以二分枚举,或者直接从1枚举时间然后加新边在原来的基础上进行增广. 谨记:时间是个不可忽视的维度. ...

  3. BZOJ2051 : A Problem For Fun

    树的点分治,将点分治的过程记录下来,每一个分治结构按到分治中心的距离维护所有点. 对于一个点二分答案,然后在$O(\log n)$个分治结构中二分查找,时间复杂度$O(n\log^3n)$. #inc ...

  4. TYVJ P1045 &&洛谷 1388 最大的算式 Label:dp

    描述 题目很简单,给出N个数字,不改变它们的相对位置,在中间加入K个乘号和N-K-1个加号,(括号随便加)使最终结果尽量大.因为乘号和加号一共就是N-1个了,所以恰好每两个相邻数字之间都有一个符号.例 ...

  5. 【COGS & USACO】896. 圈奶牛(凸包)

    http://cojs.tk/cogs/problem/problem.php?pid=896 我的计算几何入门题... 看了看白书的计算几何部分,,恩好嘛.. 乃们都用向量!!!! 干嘛非要将2个点 ...

  6. BZOJ1367 [Baltic2004]sequence

    现学的左偏树...这可是道可并堆的好题目. 首先我们考虑z不减的情况: 我们发现对于一个区间[l, r],里面是递增的,则对于此区间最优解为z[i] = t[i]: 如果里面是递减的,z[l] = z ...

  7. Json 数组拼接

    var str1 = {"name": "apple", "sex": "21"};                 / ...

  8. ASP.NET RepeatLayout 属性

    定义和用法 RepeatLayout 属性用于设置或获取如何显示在 CheckBoxList 中的项目. 语法 <asp:CheckBoxList RepeatLayout="mode ...

  9. JAVA图片处理--缩放,切割,类型转换

    import java.io.*; import java.awt.*; import java.awt.image.*; import java.awt.Graphics; import java. ...

  10. salt执行报错一例

    执行报错: 查看服务端日志: 认证有问题 重新认证吧!!! minion端: [root@super66 ~]# cd /etc/salt/[root@super66 salt]# lsminion ...