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;}
阅读全文
0 0
- Linux下简单线程池的实现
- Linux下简单线程池的实现
- Linux下简单线程池的实现
- Linux下简单的线程池
- Linux下的一个简单的线程池
- linux下的一个简单线程安全内存池实现
- linux下的最简单的线程应用代码
- linux 下线程的简单gdb调试方法
- linux进程线程下简单的消费者和生产者
- linux下c/c++实例之十三C实现的简单的线程池
- linux 简单线程池
- 主题:一个简单的linux线程池
- 一个简单的linux线程池
- 主题:一个简单的linux线程池
- 一段简单的Linux线程池代码
- 一个简单的linux线程池
- 一个简单的linux线程池
- 简单Linux C线程池的实现
- git命令
- Java虚拟机之内存管理
- 文章标题
- CSS用border绘制三角形
- Python 二维字典更新
- Linux下简单的线程池
- 崭新印通拼版软件(ImageHarbor)下载 v6.0官方免费版
- 欢迎使用CSDN-markdown编辑器
- SQL操作表
- Jenkins Pipeline 系列—02 为什么选Pipeline
- Ext.data.Store 改成POST请求
- 数组与矩阵---在数组中找到一个局部最小的位置
- 常见编程——最长公共子序列(不连续)和最长公共子串(连续)
- QT 历史版本下载