Linux下简单的线程池

来源:互联网 发布:淘宝网络红人 编辑:程序博客网 时间:2024/06/06 23:55
1.为什么需要线程池?
一般情况下,我们在处理高并发的数据量的时候,对每一个用户创建一个线程用来处理,任务完成后,销毁线程。
假设时间开销 1.线程创建时间 2.线程执行时间 3.线程的销毁时间
2.线程池原理
线程池采用预创建的技术,在应用程序启动之后,立即创建一定数量的线程,放入空闲队列中,这些线程处于阻塞状态,不消耗CPU,只占用较小的内存。当创建的线程全部处于运行阶段,线程池将自动创建一定数量的线程放入线程池中用来处理更多的任务,当大部分线程处于暂停状态时,线程池自动销毁一部分线程,回收资源。
3.线程池框架
线程池:用于创建并管理线程
工作线程:线程池中实际执行的线程
任务接口:抽象线程执行的任务形成接口(执行函数及参数)
任务队列:实际实现中可能是一些常用的数据结构队列链表,保存线程

#include <stdio.h>#include <pthread.h>#include <stdlib.h>#include <errno.h>#include <unistd.h>/*   线程池中任务队列的任务节点 */struct TaskNode{//线程处理任务时要执行的函数 void* (*func)(void* arg);//执行任务时的参数void* arg;struct TaskNode* pre;//前驱节点struct TaskNode* next;//后继节点};typedef struct TaskNode TaskNode;struct ThreadPool{//线程同步机制pthread_mutex_t mutex;pthread_cond_t notify;int close;//0表示不销毁 1表示销毁线程池int run_num;//处于运行的线程的个数int pthread_num;//线程创建的个数pthread_t *pth;//线程数组的指针int task_count;//节点(任务)的个数int size;//最多的任务数量TaskNode* head;//队列的头部TaskNode* tail;//队列的尾部};typedef struct ThreadPool ThreadPool;void* thread_task(void *threadpool){ThreadPool *pool = (ThreadPool *)threadpool;while(1){pthread_mutex_lock(&pool->mutex);//任务队列中没有任务时while( 0 == pool->task_count && pool->close != 1 ){//等待任务//当条件变量满足后会对信号量 再次加锁pthread_cond_wait(&pool->notify, &pool->mutex);}//如果此时线程池要销毁了if( 1 == pool->close ){pthread_mutex_unlock(&pool->mutex);printf("pthread id is 0x%x exited\n", (unsigned int)pthread_self());pthread_exit(NULL);}//获取要执行的具体任务并执行 temp用于释放头结点的空间以及具体的任务 TaskNode* temp;temp = pool->head;if(NULL == pool->head->next){pool->head = pool->tail = NULL;}else{pool->head = pool->head->next;if(NULL == pool->head){pool->tail = pool->head;pool->head->pre = NULL;} }pool->task_count--;pthread_mutex_unlock(&pool->mutex);printf("start %d\n",*(int *)temp->arg);//执行任务 函数指针(*(temp->func))(temp->arg);free(temp);}return NULL;}/*创建线程池   pthread_num 线程池中线程的个数  max_task_size 任务队列中最多的任务数量*/ThreadPool* threadpool_create(int pthread_num, int max_task_size){//迭代创建线程池中的线程的计数器int i;ThreadPool* pool = (ThreadPool*)malloc(sizeof(ThreadPool));if(NULL == pool){perror("malloc fail\n");exit(-1);}//初始化操作pool->close = 0;pool->pthread_num = pthread_num;pool->size = max_task_size;pool->run_num = 0;pool->pthread_num = 0;pool->head = pool->tail = NULL;pool->pth = NULL;//对线程同步需要的信号量与条件进行初始化if( 0 != pthread_mutex_init(&pool->mutex, NULL) || 0 != pthread_cond_init(&pool->notify, NULL) ){perror("pthread_init fail\n");exit(-2);}//要创建的线程分配存储空间pool->pth = (pthread_t*)malloc( sizeof(pthread_t) * pthread_num );if( NULL == pool->pth ){perror("malloc fail\n");exit(-1);}for(i=0; i<pthread_num; i++){//pthread_thread 为线程执行的具体函数//pool没有看完所有代码之前可能没有反应过来, 线程池中有需要执行的具体任务的参数 所以传递的为线程池指针,通过线程池指针, 在去获取具体执行的任务pthread_create(&pool->pth[i], NULL, thread_task, (void*)pool);printf("create pthread id 0x%x\n",(unsigned int)pool->pth[i]);//此时才对相关的引用计数增加pool->pthread_num++;pool->run_num++;}return pool;}//向任务队列中添加任务 void add_task_threadpool(ThreadPool* pool, void* (*func)(void* arg), void* arg){if(NULL == pool)exit(0);//任务队列已满if(pool->task_count == pool->size){perror("task too much\n");sleep(5);}TaskNode *task = (TaskNode*)malloc(sizeof(TaskNode));if(NULL == task){perror("malloc fail\n");exit(-1);}task->func = func;task->arg = arg;task->next = NULL;task->pre = NULL;//涉及到多个线程修改(添加 删除等方式)数据时一定要保证数据的同步pthread_mutex_lock(&pool->mutex);//队列为空if(NULL == pool->head){pool->head = task;pool->tail = task;}else{pool->tail->next = task;task->pre = pool->tail;pool->tail = task;}pool->task_count++;pthread_mutex_unlock(&pool->mutex);//此时队列中有任务,唤醒线程池中的线程去处理任务pthread_cond_signal(&pool->notify);} //线程池的销毁操作void threadpool_destroy(ThreadPool* pool){if(NULL == pool)exit(0);//已经调用过if(1 == pool->close)exit(0);pool->close = 1;int i;//唤醒应条件变量阻塞的线程pthread_cond_broadcast(&pool->notify);//阻塞回收线程的资源for(i=0; i<pool->pthread_num; i++)pthread_join(pool->pth[i], NULL);TaskNode *p = pool->head;while(NULL != p){pool->head = p->next;p->next->pre = NULL;free(p); }pthread_cond_destroy(&pool->notify);pthread_mutex_destroy(&pool->mutex);free(pool->pth);free(pool);pool->pth = NULL;pool = NULL;}void* print(void* arg){printf("pthread id %x\t%d\n",(unsigned int)pthread_self(), *(int*)arg);}int main(){int i=0;ThreadPool *pool = threadpool_create(5, 1000);printf("pthread num is %d\n",pool->pthread_num);int* buf = (int*)malloc(sizeof(int) *500 );while(i<500){buf[i] = i;add_task_threadpool(pool, print, (void*)&buf[i]);printf("task num is %d\n",pool->task_count);i++;}sleep(5);threadpool_destroy(pool);free(buf);return 0;}