原文转自: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. Xamarin iOS开发中的编辑、连接、运行

    Xamarin iOS开发中的编辑.连接.运行 创建好工程后,就可以单击Xamarin Studio上方的运行按钮,如图1.37所示,对HelloWorld项目进行编辑.连接以及运行了.运行效果如图1 ...

  2. 递推DP URAL 1009 K-based Numbers

    题目传送门 题意:n位数,k进制,求个数分析:dp[i][j] 表示i位数,当前数字为j的个数:若j==0,不加dp[i-1][0]; 代码1: #include <cstdio> #in ...

  3. BZOJ3743 : [Coci2014]Kamp

    d[x][0]表示x点向下走且回到x点的最少代价 d[x][1]表示x点向下走但不回到x点的最少代价 d[x][2]表示x点向下走的最长路 d[x][3]表示x点向下走的次长路 u[x][0]表示x点 ...

  4. TYVJ P1086 Elevator Label:dp

    背景 广东汕头聿怀初中 Train#2 Problem4 描述 现有N种箱子,每种箱子高度H_i,数量C_i.现选取若干箱子堆成一列,且第i种箱子不能放在高度超过A_i的地方.试求最大叠放高度. 输入 ...

  5. Windows环境下Redis

    Redis 是一个高性能的key-value数据库, 使用内存作为主存储,数据访问速度非常快,当然它也提供了两种机制支持数据持久化存储.比较遗憾的是,Redis项目不直接支持Windows,Windo ...

  6. 再析在spring框架中解决多数据源的问题

    在前面我写了<如何在spring框架中解决多数据源的问题>,通过设计模式中的Decorator模式在spring框架中解决多数据源的问题,得到了许多网友的关注.在与网友探讨该问题的过程中, ...

  7. 如何在spring框架中解决多数据源的问题

    在我们的项目中遇到这样一个问题:我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库.我们以往在spring和hibernate框架中总是配置一个数据源,因而sessi ...

  8. sql2005 全文索引

    1.打开全文索引 一.检查服务里面带有Full-text字样的服务是否存在并开启! [](http://images2015.cnblogs.com/blog/23017/201611/23017-2 ...

  9. centos fastdfs 多服务器 多硬盘 多组 配置详解

    说正文前,先感谢happy_fish100提供的fastdfs,轻量级的分布式文件服务器. 随着用户量的变大,图片,视频等的量会不断的增大,这个时候一个硬盘可能不够用了,就要加硬盘.硬盘加不了时,就要 ...

  10. ASP.NET MVC4系列验证机制、伙伴类共享源数据信息(数据注解和验证)

    一,mvc前后台验证 自定义属性标签MyRegularExpression using System; using System.Collections.Generic; using System.C ...