简单的线程池
来源:互联网 发布:通联数据股份有限公司 编辑:程序博客网 时间:2024/04/30 05:22
1.线程池基本原理
该图来自:http://blog.csdn.net/turkeyzhou/article/details/8755976
一般来说实现一个线程池主要包括以下几个组成部分:
1)线程管理器:用于创建并管理线程池。
2)工作线程:线程池中实际执行任务的线程。在初始化线程时会预先创建好固定数目的线程在池中,这些初始化的线程一般处于空闲状态,一般不占用CPU,占用较小的内存空间。
3)任务接口:每个任务必须实现的接口,当线程池的任务队列中有可执行任务时,被空闲的工作线程调去执行(线程的闲与忙是通过互斥量实现的,跟前面文章中的设置标志位差不多),把任务抽象出来形成接口,可以做到线程池与具体的任务无关。
4)任务队列:用来存放没有处理的任务,提供一种缓冲机制,实现这种结构有好几种方法,常用的是队列,主要运用先进先出原理,另外一种是链表之类的数据结构,可以动态的为它分配内存空间,应用中比较灵活,下文中就是用到的链表。
下面的不在赘述百度《线程池技术在并发服务器中的应用》写的非常详细!
转自:http://blog.csdn.net/zouxinfox/article/details/3560891
这里记录一下自己弄个的一个简单的线程池;
头文件:
/* * Thread_pool.h * * Created on: 2016年4月11日 * Author: wenjun */#ifndef THREAD_POOL_H_#define THREAD_POOL_H_#include <pthread.h>#include <stdio.h>#include <errno.h>#include <time.h>//线程任务typedef struct thread_task{ void *(*run)(void *arg);//线程执行函数 void *arg;//函参 struct thread_task *next;}thr_task;//协同条件typedef struct thread_condition{ pthread_cond_t thr_cond_t;//条件变量 pthread_mutex_t thr_mutex_t;//互斥锁}thr_condition;//线程池typedef struct thread_pool{ thr_condition ready;//线程协调条件 thr_task *first;//任务链表头指针 thr_task *tail;//任务链表尾指针 int idle;//空闲现正数 int counter;//当前线程池线程数 int max_threads;//最大线程数 int quit;//现正需要摧毁标志}thr_pool;//初始化线程条件int condition_init(thr_condition *cond){ int flag = 0; //初始化互斥量 if((flag = pthread_mutex_init(&cond->thr_mutex_t, NULL)) != 0) { printf("pthread_mutex_init failed %d\n",flag); return -1; } //初始化条件变量 if((flag = pthread_cond_init(&cond->thr_cond_t, NULL)) != 0) { printf("pthread_condition_init failed %d\n", flag); return -1; } return 0;}//申请互斥锁int condition_lock(thr_condition *cond){ return pthread_mutex_lock(&cond->thr_mutex_t);}//释放互斥锁int condition_unlock(thr_condition *cond){ return pthread_mutex_unlock(&cond->thr_mutex_t);}//申请条件锁int condition_timewait(thr_condition *cond, const struct timespec *tsptr){ int statu = pthread_cond_timedwait(&cond->thr_cond_t, &cond->thr_mutex_t, tsptr); return statu;}//申请条件锁int condition_wait(thr_condition *cond){ return pthread_cond_wait(&cond->thr_cond_t, &cond->thr_mutex_t);}//发送条件条件锁信号int condition_signal(thr_condition *cond){ return pthread_cond_signal(&cond->thr_cond_t);}//发送条件锁广播int condition_broadcast(thr_condition *cond){ return pthread_cond_broadcast(&cond->thr_cond_t);}//销毁线程条件变量int condition_destroy(thr_condition *cond){ int flag = 0; //销毁互斥量 if((flag = pthread_mutex_destroy(&cond->thr_mutex_t)) != 0) { printf("pthread_mutex_destroy failed %d\n",flag); return -1; } //销毁条件变量 if((flag = pthread_cond_destroy(&cond->thr_cond_t)) != 0) { printf("pthread_condition_destroy failed %d\n", flag); return -1; } return 0;}//线程执行函数void *thread_routine(void *arg){ struct timespec abstime; int timeout; printf("thread 0x%x is starting\n", (int)pthread_self()); thr_pool *pool = (thr_pool *)arg; //等待与处理任务 while(1) { condition_lock(&pool->ready); pool->idle++; //等待任务 while(pool->first && !pool->quit) { timeout = 0; clock_gettime(CLOCK_REALTIME, &abstime); abstime.tv_sec += 1000; printf("thread 0x%x is waiting\n", (int)pthread_self()); int status = condition_timewait(&pool->ready, &abstime); if(status == ETIMEDOUT ||status != 0) { printf("thread 0x%x is wait timed out \n", (int)pthread_self()); timeout = 1; break; } printf("thread 0x%x is wait ending \n", (int)pthread_self()); } //执行任务 if(pool->first != NULL) { thr_task *task = pool->first; pool->first = pool->first->next; condition_unlock(&pool->ready); task->run(task->arg); //销毁执行完的任务 free(task); } //判断是是否需要退出该线程(强制退去) if(pool->quit && pool->first==NULL) { pool->counter--; if(pool->counter == 0) condition_signal(&pool->ready); condition_unlock(&pool->ready); break; } //判断是是否需要退出该线程(无任务) if(timeout && pool->first) { pool->counter--; if(pool->counter == 0) condition_signal(&pool->ready); condition_unlock(&pool->ready); break; } pool->idle--; condition_unlock(&pool->ready); } printf("thread 0x%x is ending\n", (int)pthread_self()); return NULL;}//线程池初始化void thread_pool_init(thr_pool *pool, int threads){ condition_init(&pool->ready); pool->first = NULL; pool->tail = NULL; pool->counter = 0; pool->idle = 0; pool->max_threads = threads; pool->quit = 0;}//线程池添加任务函数int thread_pool_add_task(thr_pool *pool, void *(*run(void *arg)), void *arg){ thr_task *tmp = (thr_task *) malloc(sizeof(thr_task)); if(tmp == NULL) { printf("malloc thr_task failed %d\n", errno); exit(1); } tmp->arg = arg; tmp->next = NULL; tmp->run = run; condition_lock(&pool->ready); if(pool->first == NULL) { pool->first = tmp; pool->tail = tmp; } else { pool->tail->next = tmp; pool->tail = tmp; } //如果有等待线程则发送条件满足信号否则就向线程池中添加线程 if(pool->idle > 0) { condition_signal(&pool->ready); } else if(pool->counter < pool->max_threads) { pthread_t pthr_id; int err; err = pthread_create(&pthr_id, NULL, thread_routine, pool); if(err != 0) { printf("pthread_create fialed %d\n", err); return -1; } pool->counter++; } condition_unlock(&pool->ready); return 0;}//线程池销毁函数void thread_pool_destroy(thr_pool *pool){ if(pool->quit) return; condition_lock(&pool->ready); pool->quit = 1; if(pool->counter > 0) { if(pool->idle > 0) condition_broadcast(&pool->ready); while(pool->counter > 0) { condition_wait(&pool->ready); } } condition_unlock(&pool->ready);}#endif /* THREAD_POOL_H_ */
测试文件:
/* * thread_pool_test.c * * Created on: 2016年4月11日 * Author: wenjun */#include "Thread_pool.h"#include <unistd.h>#include <stdio.h>#include <stdlib.h>void* pool_task_test(void *arg){ printf("thread 0x%x is working on task %d\n", (int)pthread_self(), *(int *)arg); free(arg); sleep(1); return NULL;}int main(void){ thr_pool pool; thread_pool_init(&pool, 4); int i; for(i = 0; i<20 ;++i) { int *arg = (int *)malloc(sizeof(int)); if(arg ==NULL) { printf("malloc thr_task failed %d\n", errno); exit(1); } *arg = i; thread_pool_add_task(&pool, pool_task_test, arg); } sleep(3); thread_pool_destroy(&pool); return 0;}
结果:
0 0
- 简单的线程池
- 简单的线程池
- 简单的线程池
- 简单的线程池
- 简单的线程池
- 简单的线程池
- 关于简单的线程池
- 一个简单的线程池
- 简单的Java线程池
- 简单的线程池实现
- 一个简单的线程池
- 一个简单的线程池
- 线程池的简单实现
- 简单线程池的实现
- 一个简单的线程池
- 线程池的简单使用
- 一个简单的线程池
- 最简单的线程池
- 金块问题
- QNX虚拟机与宿主机(Win7)共享文件夹
- 【华为机试题】删除输入字符串中重复字符
- ArrayList
- IOS手指触摸滑动
- 简单的线程池
- 原创测试二
- 话不能说太多,不能说太透
- Android断网后让用户进入到系统设置界面设置网络
- eclipse插件的文件更新事件执行流程
- Java就业面试题大全
- matlab矩阵操作
- apache安装
- ASCII、Unicode、GBK和UTF-8字符编码的区别联系