日常咱们使用new、malloc在堆区申请一块内存,但因为每次申请的内存大小不同就会产生不少内存碎片,形成很差管理与浪费的状况。ios
内存池则是在真正使用内存以前,先申请分配必定数量的、大小相等(通常状况下)的内存块留做备用。当有新的内存需求时,就从内存池中分出一部份内存块,若内存块不够再继续申请新的内存。这样作的一个显著优势是尽可能避免了内存碎片,使得内存分配效率获得提高。程序员
这两个问题有必定的类似度,在面向对象程序编程中,对象的建立与析构都是一个较为复杂的过程,较费时间,因此为了提升程序的运行效率尽量减小建立和销毁对象的次数,特别是一些很耗资源的对象建立和销毁。编程
因此咱们能够建立一个进程池(线程池),预先放一些进程(线程)进去,要用的时候就直接调用,用完以后再把进程归还给进程池,省下建立删除进程的时间,不过固然就须要额外的开销了。
利用线程池与进程池可使管理进程与线程的工做交给系统管理,不须要程序员对里面的线程、进程进行管理。服务器
一、须要大量的线程来完成任务,且完成任务的时间比较短。 WEB服务器完成网页请求这样的任务,使用线程池技术是很是合适的。由于单个任务小,而任务数量巨大,你能够想象一个热门网站的点击次数。但对于长时间的任务,好比一个Telnet链接请求,线程池的优势就不明显了。由于Telnet会话时间比线程的建立时间大多了。网络
二、对性能要求苛刻的应用,好比要求服务器迅速响应客户请求。多线程
三、接受突发性的大量请求,但不至于使服务器所以产生大量线程的应用。突发性大量客户请求,在没有线程池状况下,将产生大量线程,虽然理论上大部分操做系统线程数目最大值不是问题,短期内产生大量线程可能使内存到达极限,并出现"OutOfMemory"的错误。并发
首先说一下多线程的好处:多线程技术主要解决处理器单元内多个线程执行的问题,它能够显著减小处理器单元的闲置时间,增长处理器单元的吞吐能力。函数
咱们知道应用程序建立一个对象,而后销毁对象是很耗费资源的。建立线程,销毁线程,也是如此。所以,咱们就预先生成一些线程,等到咱们使用的时候在进行调度,因而,一些"池化资源"技术就这样的产生了。性能
本文所提到服务器程序是指可以接受客户请求并能处理请求的程序,而不仅是指那些接受网络客户请求的网络服务器程序。网站
多线程技术主要解决处理器单元内多个线程执行的问题,它能够显著减小处理器单元的闲置时间,增长处理器单元的吞吐能力。但若是对多线程应用不当,会增长对单个任务的处理时间。能够举一个简单的例子:
假设在一台服务器完成一项任务的时间为T
T1 建立线程的时间
T2 在线程中执行任务的时间,包括线程间同步所需时间
T3 线程销毁的时间
显然T = T1+T2+T3。注意这是一个极度简化的假设。
能够看出T1,T3是多线程自己的带来的开销,咱们渴望减小T1,T3所用的时间,从而减小T的时间。但一些线程的使用者并无注意到这一点,因此在程序中频繁的建立或销毁线程,这致使T1和T3在T中占有至关比例。显然这是突出了线程的弱点(T1,T3),而不是优势(并发性)。
线程池技术正是关注如何缩短或调整T1,T3时间的技术,从而提升服务器程序性能的。它把T1,T3分别安排在服务器程序的启动和结束的时间段或者一些空闲的时间段,这样在服务器程序处理客户请求时,不会有T1,T3的开销了。
线程池不只调整T1,T3产生的时间段,并且它还显著减小了建立线程的数目。在看一个例子:
假设一个服务器一天要处理50000个请求,而且每一个请求须要一个单独的线程完成。咱们比较利用线程池技术和不利于线程池技术的服务器处理这些请求时所产生的线程总数。在线程池中,线程数通常是固定的,因此产生线程总数不会超过线程池中线程的数目或者上限(如下简称线程池尺寸),而若是服务器不利用线程池来处理这些请求则线程总数为50000。通常线程池尺寸是远小于50000。因此利用线程池的服务器程序不会为了建立50000而在处理请求时浪费时间,从而提升效率。
#ifndef __THREAD_H #define __THREAD_H #include <vector> #include <string> #include <pthread.h> using namespace std; /** * 执行任务的类,设置任务数据并执行 */ class CTask { protected: string m_strTaskName; /** 任务的名称 */ void* m_ptrData; /** 要执行的任务的具体数据 */ public: CTask(){} CTask(const string& taskName) { m_strTaskName = taskName; m_ptrData = NULL; } virtual ~CTask(){} virtual int Run() = 0; void SetData(void* data); /** 设置任务数据 */ }; /** * 线程池管理类的实现 */ class CThreadPool { private: static vector<CTask*> m_vecTaskList; /** 任务列表 */ static bool shutdown; /** 线程退出标志 */ int m_iThreadNum; /** 线程池中启动的线程数 */ pthread_t *pthread_id; static pthread_mutex_t m_pthreadMutex; /** 线程同步锁 */ static pthread_cond_t m_pthreadCond; /** 线程同步的条件变量 */ protected: static void* ThreadFunc(void * threadData); /** 新线程的线程回调函数 */ static int MoveToIdle(pthread_t tid); /** 线程执行结束后,把本身放入到空闲线程中 */ static int MoveToBusy(pthread_t tid); /** 移入到忙碌线程中去 */ int Create(); /** 建立线程池中的线程 */ public: CThreadPool(int threadNum = 10); int AddTask(CTask *task); /** 把任务添加到任务队列中 */ int StopAll(); /** 使线程池中的线程退出 */ int getTaskSize(); /** 获取当前任务队列中的任务数 */ }; #endif
thread.cpp:
#include "Thread.h" #include <iostream> #include "stdlib.h" void CTask::SetData(void * data) { m_ptrData = data; } vector<CTask*> CThreadPool::m_vecTaskList; //任务列表 bool CThreadPool::shutdown = false; pthread_mutex_t CThreadPool::m_pthreadMutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t CThreadPool::m_pthreadCond = PTHREAD_COND_INITIALIZER; /** * 线程池管理类构造函数 */ CThreadPool::CThreadPool(int threadNum) { this->m_iThreadNum = threadNum; cout << "I will create " << threadNum << " threads" << endl; Create(); } /** * 线程回调函数 */ void* CThreadPool::ThreadFunc(void* threadData) { pthread_t tid = pthread_self(); while (1) { pthread_mutex_lock(&m_pthreadMutex); while (m_vecTaskList.size() == 0 && !shutdown) { pthread_cond_wait(&m_pthreadCond, &m_pthreadMutex); } if (shutdown) { pthread_mutex_unlock(&m_pthreadMutex); printf("thread %lu will exit\n", pthread_self()); pthread_exit(NULL); } printf("tid %lu run\n", tid); vector<CTask*>::iterator iter = m_vecTaskList.begin(); /** * 取出一个任务并处理之 */ CTask* task = *iter; if (iter != m_vecTaskList.end()) { task = *iter; m_vecTaskList.erase(iter); } pthread_mutex_unlock(&m_pthreadMutex); task->Run(); /** 执行任务 */ printf("tid:%lu idle\n", tid); } return (void*)0; } /** * 往任务队列里边添加任务并发出线程同步信号 */ int CThreadPool::AddTask(CTask *task) { pthread_mutex_lock(&m_pthreadMutex); this->m_vecTaskList.push_back(task); pthread_mutex_unlock(&m_pthreadMutex); pthread_cond_signal(&m_pthreadCond); return 0; } /** * 建立线程 */ int CThreadPool::Create() { pthread_id = (pthread_t*)malloc(sizeof(pthread_t) * m_iThreadNum); for(int i = 0; i < m_iThreadNum; i++) { pthread_create(&pthread_id[i], NULL, ThreadFunc, NULL); } return 0; } /** * 中止全部线程 */ int CThreadPool::StopAll() { /** 避免重复调用 */ if (shutdown) { return -1; } printf("Now I will end all threads!!\n"); /** 唤醒全部等待线程,线程池要销毁了 */ shutdown = true; pthread_cond_broadcast(&m_pthreadCond); /** 阻塞等待线程退出,不然就成僵尸了 */ for (int i = 0; i < m_iThreadNum; i++) { pthread_join(pthread_id[i], NULL); } free(pthread_id); pthread_id = NULL; /** 销毁条件变量和互斥体 */ pthread_mutex_destroy(&m_pthreadMutex); pthread_cond_destroy(&m_pthreadCond); return 0; } /** * 获取当前队列中任务数 */ int CThreadPool::getTaskSize() { return m_vecTaskList.size(); }
main.cpp:
#include "Thread.h" #include <iostream> #include <unistd.h> #include <stdlib.h> class CMyTask: public CTask { public: CMyTask(){} inline int Run() { printf("%s\n", (char*)this->m_ptrData); sleep(10); return 0; } }; int main() { CMyTask taskObj; char szTmp[] = "this is the new thread running"; taskObj.SetData((void*)szTmp); CThreadPool threadPool(10); for(int i = 0; i < 20; i++) { threadPool.AddTask(&taskObj); } while(1) { printf("there are still %d tasks need to handle\n", threadPool.getTaskSize()); if (threadPool.getTaskSize() == 0) { if (threadPool.StopAll() == -1) { printf("Now I will exit from main\n"); exit(0); } } sleep(2); } return 0; }