`
javathinker
  • 浏览: 227052 次
  • 来自: ...
文章分类
社区版块
存档分类
最新评论

C语言实现简单线程池

 
阅读更多

有时我们会需要大量线程来处理一些相互独立的任务,为了避免频繁的申请释放线程所带来的开销,我们可以使用线程池。下面是一个C语言实现的简单的线程池。

头文件:

   1: #ifndef THREAD_POOL_H__
   2: #define THREAD_POOL_H__
   3: 
   4: #include <pthread.h>
   5: 
   6: /* 要执行的任务链表 */
   7: typedef struct tpool_work {
   8:     void*               (*routine)(void*);       /* 任务函数 */
   9:     void                *arg;                    /* 传入任务函数的参数 */
  10:     struct tpool_work   *next;                    
  11: }tpool_work_t;
  12: 
  13: typedef struct tpool {
  14:     int             shutdown;                    /* 线程池是否销毁 */
  15:     int             max_thr_num;                /* 最大线程数 */
  16:     pthread_t       *thr_id;                    /* 线程ID数组 */
  17:     tpool_work_t    *queue_head;                /* 线程链表 */
  18:     pthread_mutex_t queue_lock;                    
  19:     pthread_cond_t  queue_ready;    
  20: }tpool_t;
  21: 
  22: /*
  23:  * @brief     创建线程池 
  24:  * @param     max_thr_num 最大线程数
  25:  * @return     0: 成功 其他: 失败  
  26:  */
  27: int
  28: tpool_create(int max_thr_num);
  29: 
  30: /*
  31:  * @brief     销毁线程池 
  32:  */
  33: void
  34: tpool_destroy();
  35: 
  36: /*
  37:  * @brief     向线程池中添加任务
  38:  * @param    routine 任务函数指针
  39:  * @param     arg 任务函数参数
  40:  * @return     0: 成功 其他:失败 
  41:  */
  42: int
  43: tpool_add_work(void*(*routine)(void*), void *arg);
  44: 
  45: #endif

实现:

   1: #include <unistd.h>
   2: #include <stdlib.h>
   3: #include <errno.h>
   4: #include <string.h>
   5: #include <stdio.h>
   6: 
   7: #include "tpool.h"
   8: 
   9: static tpool_t *tpool = NULL;
  10: 
  11: /* 工作者线程函数, 从任务链表中取出任务并执行 */
  12: static void* 
  13: thread_routine(void *arg)
  14: {
  15:     tpool_work_t *work;
  16:     
  17:     while(1) {
  18:         /* 如果线程池没有被销毁且没有任务要执行,则等待 */
  19:         pthread_mutex_lock(&tpool->queue_lock);
  20:         while(!tpool->queue_head && !tpool->shutdown) {
  21:             pthread_cond_wait(&tpool->queue_ready, &tpool->queue_lock);
  22:         }
  23:         if (tpool->shutdown) {
  24:             pthread_mutex_unlock(&tpool->queue_lock);
  25:             pthread_exit(NULL);
  26:         }
  27:         work = tpool->queue_head;
  28:         tpool->queue_head = tpool->queue_head->next;
  29:         pthread_mutex_unlock(&tpool->queue_lock);
  30: 
  31:         work->routine(work->arg);
  32:         free(work);
  33:     }
  34:     
  35:     return NULL;   
  36: }
  37: 
  38: /*
  39:  * 创建线程池 
  40:  */
  41: int
  42: tpool_create(int max_thr_num)
  43: {
  44:     int i;
  45: 
  46:     tpool = calloc(1, sizeof(tpool_t));
  47:     if (!tpool) {
  48:         printf("%s: calloc failed\n", __FUNCTION__);
  49:         exit(1);
  50:     }
  51:     
  52:     /* 初始化 */
  53:     tpool->max_thr_num = max_thr_num;
  54:     tpool->shutdown = 0;
  55:     tpool->queue_head = NULL;
  56:     if (pthread_mutex_init(&tpool->queue_lock, NULL) !=0) {
  57:         printf("%s: pthread_mutex_init failed, errno:%d, error:%s\n",
  58:             __FUNCTION__, errno, strerror(errno));
  59:         exit(1);
  60:     }
  61:     if (pthread_cond_init(&tpool->queue_ready, NULL) !=0 ) {
  62:         printf("%s: pthread_cond_init failed, errno:%d, error:%s\n", 
  63:             __FUNCTION__, errno, strerror(errno));
  64:         exit(1);
  65:     }
  66:     
  67:     /* 创建工作者线程 */
  68:     tpool->thr_id = calloc(max_thr_num, sizeof(pthread_t));
  69:     if (!tpool->thr_id) {
  70:         printf("%s: calloc failed\n", __FUNCTION__);
  71:         exit(1);
  72:     }
  73:     for (i = 0; i < max_thr_num; ++i) {
  74:         if (pthread_create(&tpool->thr_id[i], NULL, thread_routine, NULL) != 0){
  75:             printf("%s:pthread_create failed, errno:%d, error:%s\n", __FUNCTION__, 
  76:                 errno, strerror(errno));
  77:             exit(1);
  78:         }
  79:         
  80:     }    
  81: 
  82:     return 0;
  83: }
  84: 
  85: /* 销毁线程池 */
  86: void
  87: tpool_destroy()
  88: {
  89:     int i;
  90:     tpool_work_t *member;
  91: 
  92:     if (tpool->shutdown) {
  93:         return;
  94:     }
  95:     tpool->shutdown = 1;
  96: 
  97:     /* 通知所有正在等待的线程 */
  98:     pthread_mutex_lock(&tpool->queue_lock);
  99:     pthread_cond_broadcast(&tpool->queue_ready);
 100:     pthread_mutex_unlock(&tpool->queue_lock);
 101:     for (i = 0; i < tpool->max_thr_num; ++i) {
 102:         pthread_join(tpool->thr_id[i], NULL);
 103:     }
 104:     free(tpool->thr_id);
 105: 
 106:     while(tpool->queue_head) {
 107:         member = tpool->queue_head;
 108:         tpool->queue_head = tpool->queue_head->next;
 109:         free(member);
 110:     }
 111: 
 112:     pthread_mutex_destroy(&tpool->queue_lock);    
 113:     pthread_cond_destroy(&tpool->queue_ready);
 114: 
 115:     free(tpool);    
 116: }
 117: 
 118: /* 向线程池添加任务 */
 119: int
 120: tpool_add_work(void*(*routine)(void*), void *arg)
 121: {
 122:     tpool_work_t *work, *member;
 123:     
 124:     if (!routine){
 125:         printf("%s:Invalid argument\n", __FUNCTION__);
 126:         return -1;
 127:     }
 128:     
 129:     work = malloc(sizeof(tpool_work_t));
 130:     if (!work) {
 131:         printf("%s:malloc failed\n", __FUNCTION__);
 132:         return -1;
 133:     }
 134:     work->routine = routine;
 135:     work->arg = arg;
 136:     work->next = NULL;
 137: 
 138:     pthread_mutex_lock(&tpool->queue_lock);    
 139:     member = tpool->queue_head;
 140:     if (!member) {
 141:         tpool->queue_head = work;
 142:     } else {
 143:         while(member->next) {
 144:             member = member->next;
 145:         }
 146:         member->next = work;
 147:     }
 148:     /* 通知工作者线程,有新任务添加 */
 149:     pthread_cond_signal(&tpool->queue_ready);
 150:     pthread_mutex_unlock(&tpool->queue_lock);
 151: 
 152:     return 0;    
 153: }
 154:     
 155: 

测试代码:

   1: #include <unistd.h>
   2: #include <stdio.h>
   3: #include <stdlib.h>
   4: #include "tpool.h"
   5: 
   6: void *func(void *arg)
   7: {
   8:     printf("thread %d\n", (int)arg);
   9:     return NULL;
  10: }
  11: 
  12: int
  13: main(int arg, char **argv)
  14: {
  15:     if (tpool_create(5) != 0) {
  16:         printf("tpool_create failed\n");
  17:         exit(1);
  18:     }
  19:     
  20:     int i;
  21:     for (i = 0; i < 10; ++i) {
  22:         tpool_add_work(func, (void*)i);
  23:     }
  24:     sleep(2);
  25:     tpool_destroy();
  26:     return 0;
  27: }

这个实现是在调用tpool_destroy之后,仅将当前正在执行的任务完成之后就会退出,我们也可以修改代码使得线程池在执行完任务链表中所有任务后再退出。

分享到:
评论

相关推荐

    C语言实现简单线程池.zip

    由C语言实现简单的线程池,任务调配,合理创建销毁线程处理任务

    C语言实现的简单线程池

    C语言实现的简单线程池

    线程池实现,通过C语言实现

    linux下通过200行C代码实现简单线程池,附源代码和文档说明: 200行C代码实现简单线程池.doc threadpool.c

    linux线程池的C语言实现

    通常我们使用多线程的方式是,需要时创建一个新的线程,在这个新的线程里执行特定的...这在一般的应用里已经能够满足我们应用的需要,毕竟我们并不是什么时候都需要创建大量的线程,并在它们执行一个简单的任务后销毁。

    线程池Linux C语言简单版本

    本线程池采用C语言实现。包括以下内容 &gt; - thread_pool_create:创建线程池所需要的资源,包含不限于任务队列,子线程的创建。 &gt; - thread_pool_post:用于任务的发布,将执行任务存在任务队列中。 &gt; - thread_pool_...

    Threadpool 轻量型 基于 pthread 实现的简单线程池 C语言

    一款基于 pthread 实现的简单线程池的工具类

    C++实现线程池的简单方法示例

    主要给大家介绍了关于C++实现线程池的简单方法,文中通过示例代码介绍的非常详细,对大家学习或者使用C++具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

    轻量级C语言线程池库,可用于网络编程等并发环境

    线程池库是一个用于管理线程的集合,以实现并发执行任务的库。...更易于管理:线程池提供了一组函数,用于创建、分配和管理线程,使得线程的管理更加简单和方便。 文件中提供了操作markdown格式的文档,可放心食用。

    阿里云开放存储服务的C语言SDKOSSC.zip

    OSSC(Aliyun Open Storage Service C SDK)为阿里云开放存储服务(OSS)提供了一套完整... 实现了一个简单的线程池,并且可以多线程断点上传功能; 简易的文件夹同步上传和同步下载功能。 标签:OSSC

    使用epoll 和线程池实现简单的图片浏览服务器.zip

    使用epoll 和线程池实现简单的图片浏览服务器.zip 大学生课程设计 的课程设计 自己大二写的课程设计

    linux下的线程池实现

    简单的linux多线程实现,含互斥锁的使用

    线程池的原理与实现详解

    下面利用C语言来实现一个简单的线程池,为了使得这个线程池库使用起来更加方便,特在C实现中加入了一些OO的思想,与Objective-C不同,它仅仅是使用了struct来模拟了c++中的类,其实这种方式在linux内核中大量可见

    glib-2.0-demo.zip

    GLib由三大部分组成——GLib、GObject和GIO,GLib是一套C语言工具集,GObject是基于C语言实现的对象系统,GIO是基于GObject的一套简单易用的VFS接口。 GLib包含了字符串操作、文件操作、数据校验、编解码、字符集...

    通过c的http服务器代码-C/C++开发

    当然免不了还有 linux的多线程编程,实现了一个简单的线程池,对于各个线程之间的通信实现了一个channel, 当然最重要的是我们使用了epoll技术,让我们的服务支持高并发。下面是整个项目的架构图。 安装编译 ...

    lamphttp:c的http服务器代码

    Lamphttp HTTP服务Lamphttp是使用c语言实现的http服务,目前市面上有非常多的http服务,类似大名鼎鼎的Nginx那么对于Lamphttp存在的意义是什么呢?对于Lamphttp主要是为了理解了tcp / ip到http的中间这一阶段层的...

    python cookbook(第3版)

    11.6 通过XML-RPC实现简单的远程调用 11.7 在不同的Python解释器之间交互 11.8 实现远程方法调用 11.9 简单的客户端认证 11.10 在网络服务中加入SSL 11.11 进程间传递Socket文件描述符 11.12 理解事件驱动的...

    JAVA面试题最全集

    编写代码实现一个线程池 40.描述一下JVM加载class文件的原理机制? 41.试举例说明一个典型的垃圾回收算法? 42.请用java写二叉树算法,实现添加数据形成二叉树功能,并以先序的方式打印出来. 43.请写一个java...

    ycsocket:基于swoole的套接字框架,支持协程版MySQL,Redis连接池,已用于大型RPG游戏服务端

    orm //一个C语言扩展的ORM,本框架协程数据库需要该扩展支持, 应用场景大型RPG游戏,纯php解决方案,php + swoole + swoole_orm + zephir,这个游戏的战斗部分完全用zephir来实现,转化为php扩展,能做到同时兼顾...

Global site tag (gtag.js) - Google Analytics