前言

任何一种设计方式的引入都会带来额外的开支,是否使用,取决于能带来多大的好处和能带来多大的坏处,好处与坏处包括程序的性能、代码的可读性、代码的可维护性、程序的开发效率等。

线程池适用场合:任务比较多,需要拉起大量线程来处理;任务的处理时间相对比较短,按照线程的周期T1(创建阶段)、T2(执行阶段)、T3(销毁阶段)来算,执行阶段仅占用较少时间。

简单的线程池通常有以下功能:预创建一定数量的线程;管理线程任务,当工作线程没有事情可做时休眠自己;销毁线程池。

复杂一些的线程池有额外的调节功能:管理线程池的上限;动态调节工作线程数量,当大量工作请求到来时增加工作线程,工作请求较少时销毁部分线程。

内容部分

这次实现的是一个简单的线程池模型。

首先是线程池的头文件定义:

 1 #include<unistd.h>
 2 #include<stdlib.h>
 3 #include<iostream>
 4 #include<string>
 5 #include<string.h>
 6 #include<queue>
 7 #include<errno.h>
 8 #include<pthread.h>
 9 using namespace std;
10 
11 struct  thread_work
12 {   
13     void* (*routine)(void*);
14     void* arg;
15 };
16 
17 struct thread_pool
18 {   
19     bool ShutDown;
20     unsigned int iMaxThreadNum;
21     pthread_mutex_t pool_mutex;
22     pthread_cond_t pool_cond;
23     queue<pthread_t> Pth_IdQueue;
24     queue<thread_work> Pth_workQueue;
25 };
26 
27 thread_pool* thread_pool_create(int iThreadNum);
28 void thread_pool_destroy(thread_pool* thpool);
29 int thread_pool_add_task(thread_pool* thpool, void*(*routine)(void*), void* arg);
30 void* thread_routine(void* arg);

下面是线程池的实现:

  1 #include "ThreadPool.h"
  2 
  3 thread_pool* thread_pool_create(int iThreadMaxNum)
  4 {
  5     int iRet = 0;
  6     thread_pool* pool = new thread_pool;
  7     if(NULL == pool)
  8     {
  9         cout << "new thread_pool failed! procedure exit" << endl;
 10         return NULL;
 11     }
 12     pool->iMaxThreadNum = iThreadMaxNum;
 13     pool->ShutDown = false;
 14     if((iRet=pthread_mutex_init(&pool->pool_mutex, NULL)) != 0)
 15     {
 16         cout << __FUNCTION__ << "thread_pool init failed! error: " << strerror(iRet)  << endl;
 17         delete pool;
 18         return NULL;
 19     }
 20     if((iRet=pthread_cond_init(&pool->pool_cond, NULL)) != 0)
 21     {
 22         cout << __FUNCTION__ << "thread_cond init failed! error: " << strerror(iRet) << endl;
 23         delete pool;
 24         return NULL;
 25     }
 26     
 27     for(int i = 0; i < iThreadMaxNum; i++)
 28     {
 29         pthread_t thid = 0;
 30         if((iRet=pthread_create(&thid, NULL, thread_routine, (void*)pool)) != 0)
 31         {
 32             cout << __FUNCTION__ << " pthread_create failed, error: " << strerror(iRet) << endl;
 33             delete pool;
 34             return NULL;
 35         }
 36         else
 37         {
 38             pool->Pth_IdQueue.push(thid);
 39         }
 40     }
 41     return pool;
 42 }
 43 
 44 int thread_pool_add_task(thread_pool* thpool, void*(*routine)(void*), void* arg)
 45 {
 46     if(routine == NULL  || thpool == NULL)
 47         return -1;
 48     thread_work temp;
 49     temp.routine = routine;
 50     temp.arg = arg;
 51     pthread_mutex_lock(&(thpool->pool_mutex));
 52     thpool->Pth_workQueue.push(temp);
 53     pthread_mutex_unlock(&(thpool->pool_mutex));
 54     pthread_cond_signal(&(thpool->pool_cond));
 55     return 0;
 56 }
 57 
 58 void thread_pool_destroy(thread_pool* thpool)
 59 {
 60     if(thpool == NULL)
 61         return;
 62     pthread_mutex_lock(&(thpool->pool_mutex));
 63     thpool->ShutDown = true;
 64     while(!thpool->Pth_workQueue.empty())
 65     {
 66         thpool->Pth_workQueue.pop();
 67     }
 68     pthread_cond_broadcast(&(thpool->pool_cond));
 69     pthread_mutex_unlock(&(thpool->pool_mutex));
 70     while(!thpool->Pth_IdQueue.empty())
 71     {
 72         pthread_join(thpool->Pth_IdQueue.front(), NULL);
 73         thpool->Pth_IdQueue.pop();
 74     }
 75     pthread_mutex_destroy(&(thpool->pool_mutex));
 76     pthread_cond_destroy(&(thpool->pool_cond));
 77     delete thpool;
 78 }
 79 
 80 void* thread_routine(void* pool)
 81 {
 82     if(pool == NULL)
 83     {
 84         cout << "thread_routine params is empty, thread_exit" << endl;
 85         return NULL;
 86     }
 87     while(1)
 88     {
 89         thread_pool* p = (thread_pool*)pool;
 90         pthread_mutex_lock(&(p->pool_mutex));
 91         while(p->Pth_workQueue.empty() && !p->ShutDown)
 92         {
 93             pthread_cond_wait(&(p->pool_cond), &(p->pool_mutex));
 94         }
 95         if(p->ShutDown)
 96         {
 97             pthread_mutex_unlock(&(p->pool_mutex));
 98             return NULL;
 99         }
100         thread_work work_f;
101         work_f = p->Pth_workQueue.front();
102         p->Pth_workQueue.pop();
103         pthread_mutex_unlock(&(p->pool_mutex));
104         work_f.routine(work_f.arg);
105     }
106 }

代码都是基础知识,大家应该都能理解。

下面是一个测试的demo:

 1 #include "ThreadPool.h"
 2 
 3 void* task(void* p)
 4 {
 5     int ptI = *(int*)p;
 6     //cout << "ptr address : " << p << "ptr value : " << ptI << endl;
 7     cout << ptI << endl;
 8     return NULL;
 9 }
10 
11 int main()
12 {
13     struct thread_pool* pool = thread_pool_create(100);
14     int iArg[1000];
15     for(int i = 0; i < 1000; i++)
16     {
17         iArg[i] = i;
18         thread_pool_add_task(pool, task, &iArg[i]);
19         //cout << "thread_pool_add_task id: " << iArg[i] << endl;
20         //cout << __FUNCTION__ << " success, current task id is: " << iArg[i]  << "iArg[" << i << "] address : " << &iArg[i]  << endl;
21     }
22     thread_pool_destroy(pool);    
23 }

小结

很简单很好理解的一段代码,我却写了大半天时间,手残党鉴定完毕。

LINUX下的简单线程池的更多相关文章

  1. 在Linux下写一个线程池以及线程池的一些用法和注意点

    -->线程池介绍(大部分来自网络)  在这个部分,详细的介绍一下线程池的作用以及它的技术背景以及他提供的一些服务等.大部分内容来自我日常生活中在网络中学习到的一些概念性的东西. -->代码 ...

  2. Linux下简单线程池的实现

    大多数的网络服务器,包括Web服务器都具有一个特点,就是单位时间内必须处理数目巨大的连接请求,但是处理时间却是比较短的.在传统的多线程服务器模型中是这样实现的:一旦有个服务请求到达,就创建一个新的服务 ...

  3. Linux多线程实践(9) --简单线程池的设计与实现

    线程池的技术背景 在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源.在Java中更是如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收.所以 ...

  4. Linux下一个简单的日志系统的设计及其C代码实现

    1.概述 在大型软件系统中,为了监测软件运行状况及排查软件故障,一般都会要求软件程序在运行的过程中产生日志文件.在日志文件中存放程序流程中的一些重要信息, 包括:变量名称及其值.消息结构定义.函数返回 ...

  5. linux 条件变量与线程池

    条件变量Condition Variables 概述 1. 条件变量提供了另外一种线程同步的方式.如果没有条件变量,程序需要使用线程连续轮询(可能在临界区critical section内)方式检查条 ...

  6. 基于C++11的100行实现简单线程池

    基于C++11的100行实现简单线程池 1 线程池原理 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线程池线程都是后台线程.每个线程都使用默认的堆栈大小, ...

  7. Windows和Linux下通用的线程接口

    对于多线程开发,Linux下有pthread线程库,使用起来比较方便,而Windows没有,对于涉及到多线程的跨平台代码开发,会带来不便.这里参考网络上的一些文章,整理了在Windows和Linux下 ...

  8. linux下c语言实现简单----线程池

    这两天刚好看完linux&c这本书的进程线程部分,学长建议可以用c语言实现一个简单的线程池,也是对线程知识的一个回顾与应用.线程的优点有好多,它是"轻量级的进程",所需资源 ...

  9. 基于Linux/C++简单线程池的实现

    我们知道Java语言对于多线程的支持十分丰富,JDK本身提供了很多性能优良的库,包括ThreadPoolExecutor和ScheduleThreadPoolExecutor等.C++11中的STL也 ...

随机推荐

  1. Memcache+Cookie解决分布式系统共享登录状态------------------------------Why Memcached?

    每个用户请求向IIS发送一个请求,但IIS服务器的请求数有限,cpu支持的线程数有限,如果一秒钟向这台服务器发送10000次,那么则一般就会有问题,考虑集群, 请求数据分流,几台服务器共同对应一个公共 ...

  2. 数据备份--dump

    数据中 心操作大量的数据.当遭到破坏时,这就是一场灾难.这时候需要备份来恢复,及时你又大量的备份数据都没用,备份也肯定不是在浪费时间.你也许很幸运从 来没有经历过数据丢失.但是, 由于这种事情极少发生 ...

  3. poj 1129 Channel Allocation ( dfs )

    题目:http://poj.org/problem?id=1129 题意:求最小m,使平面图能染成m色,相邻两块不同色由四色定理可知顶点最多需要4种颜色即可.我们于是从1开始试到3即可. #inclu ...

  4. storm - 基础概念整理

    理论 Hadoop的出现虽然为大数据计算提供了一条捷径,但其仍然存在自身难以克服的缺点:实时性不足.Hadoop的一轮计算的启动需要较长时间,因此其满足不了对实时性有较高要求的场景. Storm由此应 ...

  5. UVa 1210 (高效算法设计) Sum of Consecutive Prime Numbers

    题意: 给出n,求把n写成若干个连续素数之和的方案数. 分析: 这道题非常类似大白书P48的例21,上面详细讲了如何从一个O(n3)的算法优化到O(n2)再到O(nlogn),最后到O(n)的神一般的 ...

  6. tomcat+oracle连接池

    tomcat 5.5.23 oracle 10g 全局配置 一.tomcat目录\common\lib下添加包ojdbc14.jar. 二.tomcat目录\conf\server.xml的<G ...

  7. 数组中所有重复次数大于等于minTimes的数字

    class Program { static void Main(string[] args) { int[] input = { 1, 1, 1, 2, 2, 5, 2, 4, 9, 9, 20 } ...

  8. SharePoint中修改密码的WEB Part之终极版:即可以修改AD,又可以修改本机用户密码的Web Part!!

    转:http://www.cnblogs.com/dosboy/archive/2007/08/01/838859.html 在网上查了那么多SharePoint密码修改的第三方开发,都有问题.总结下 ...

  9. lightoj 1019

    裸的最短路 dijkstra #include<cstdio> #include<string> #include<cstring> #include<ios ...

  10. chrome启用本地文件

    chrome禁止本地浏览时加载本地其他文件,可以采用添加启动参数的方式来支持 添加参数为 --allow-file-access-from-files  或者 --disable-web-securi ...