/* 小规模的Linux线程池 written by luoxiongwei E-mail:[email protected] Welcom to report bugs! 实现任务具有优先级,主要的改变在 int add_tast(task * new_task);函数 */ #ifndef __THREADPOOLS #define __THREADPOOLS #include <sys/types.h> #include <pthread.h> #include <unistd.h> #include <vector> #include <cstdio> #include <cstdlib> #include <cstring> using std::vector; struct task//队列中的任务结点 { void (*handler)(void *);//任务函数 void * data;//任务数据 /*任务优先级,约定整数值越大,则优先级越高 但是这个优先级只是一个大概的,只有当线程池 稳定的时候才有效,即线程池中线程到达最大数目 之后在添加任务优先级发挥作用。 */ int prority; }; struct work_queue_t//工作队列 { struct work_queue_t * next ; struct work_queue_t * head ; struct work_queue_t * tail ; struct task * elment ; }; //工作队列操作 work_queue_t * init_work_queue();//初始化工作队列 void destory_work_queue();//销毁工作队列 work_queue_t * remove_task();//取队首任务 int add_tast(task * new_task);//在工作队列中按照优先级插入任务 bool empty(); //线程池资源 void *thread_rounter(void *);//线程执行函数 struct work_queue_t * work_queue=NULL;//工作队列 int work_count=0;//工作队列中的元素个数 vector<pthread_t> threads;//记录所有线程的id pthread_cond_t pool_cond;//唤醒相应线程开始工作 pthread_mutex_t queue_lock;//保护工作队列,以及池中的互斥资源 int idles;//空闲线程数目 int busy;//正在执行任务的线程数目 int max_thread;//池中维持的最大线程数目 bool to_exit;//销毁线程池标志 bool validate;//线程池是否可用 //线程池操作,提供给用户操作的四个函数 void thread_pool(int init_threads_num);//建立线程池 void destroy_thread_pool();//销毁线程池 /*组装任务处理函数和处理函数参数,注意一旦该任务完成之后, 数据将会被系统释放掉,所以下一次向线程池加入任务时, 请重新组装。请保证处理函数是线程可重入的。 */ task * prod_task(void (*handler)(void *), void * data,int pro); int exec_task(task * new_task);//留给用户的调用接口 #endif //示例的工作函数 void task1(void *arg); int main() { //现在测试了池中有2个线程,12个任务。 //任务参数 char *ptr1="I am task one\n"; char *ptr2="I am task two\n"; char *ptr3="I am task three\n"; char *ptr4="I am task four\n"; char *ptr5="I am task five\n"; char *ptr6="I am task six\n"; char *ptr7="I am task seven\n"; char *ptr8="I am task eight\n"; char *ptr9="I am task nine\n"; char *ptr10="I am task ten\n"; char *ptr11="I am task eleven\n"; char *ptr12="I am task twltle\n"; //组装任务 task * task_p1=prod_task(task1,ptr1,1); task * task_p2=prod_task(task1,ptr2,2); task * task_p3=prod_task(task1,ptr3,3); task * task_p4=prod_task(task1,ptr4,4); task * task_p5=prod_task(task1,ptr5,5); task * task_p6=prod_task(task1,ptr6,6); task * task_p7=prod_task(task1,ptr7,7); task * task_p8=prod_task(task1,ptr8,8); task * task_p9=prod_task(task1,ptr9,9); task * task_p10=prod_task(task1,ptr10,10); task * task_p11=prod_task(task1,ptr11,11); task * task_p12=prod_task(task1,ptr12,12); thread_pool(2);//建立线程池,池中最多2个线程 //12个任务 exec_task(task_p1); exec_task(task_p2); exec_task(task_p3); exec_task(task_p4); exec_task(task_p5); exec_task(task_p6); exec_task(task_p7); exec_task(task_p8); exec_task(task_p9); exec_task(task_p10); exec_task(task_p11); exec_task(task_p12); /*延时,让所有任务执行完。也可以不延时, 但是可能任务还没有完成,线程池就被销毁。 */ sleep(20); destroy_thread_pool();//销毁线程池 return 0; } void task1(void *arg) { char *ptr=(char *)arg; write(STDOUT_FILENO,ptr,strlen(ptr)); } //提供给用户的外部接口之一,生成任务,提供任务的优先级 task * prod_task(void (*handler)(void *), void * data,int pro) { struct task * new_task=new task; if(!new_task) return NULL; new_task->handler=handler; new_task->data=data; new_task->prority=pro; return new_task; } //工作队列的相应操作 work_queue_t * init_work_queue() { work_queue_t *work_queue_=new work_queue_t ; if(!work_queue_) return NULL; work_queue_->head=work_queue_->tail=NULL; work_queue_->next=NULL; work_queue_->elment=NULL; work_count=0; return work_queue_; } //取队首任务,在插入的时候保证队首元素 //总是优先级最高的元素 work_queue_t * remove_task() { work_queue_t * temp; if(empty())//工作队列空 return NULL; temp=work_queue->head; work_queue->head=work_queue->head->next; work_count--; return temp; } //在工作队列中添加任务 //总是将优先级最高的任务添加在 //队首,如果插入任务优先级与队首 //元素相同,则满足FIFO原则 int add_tast(task * new_task) { work_queue_t * temp=NULL; if(empty())//队列为空 { temp=new work_queue_t ; temp->next=NULL; temp->elment=new_task; work_queue->head=work_queue->tail=temp; work_count++; return 0; } else//队列不空 { temp=new work_queue_t ; temp->next=NULL; temp->elment=new_task; work_queue_t *position=work_queue->head;//任务插入的位置的前一个位置 while(position) { if(position->elment->prority>=new_task->prority) { position=position->next; } else break; } if(position==NULL)//在队尾插入 { work_queue->tail->next=temp; work_queue->tail=temp; work_count++; return 0; } if(position==work_queue->head)//在队首插入 { temp->next=work_queue->head; work_queue->head=temp; work_count++; return 0; } //在队列中的某个位置插入 work_queue_t *pre_pos=work_queue->head;//任务插入位置的前一个结点位置 while(pre_pos->next!=position) pre_pos=pre_pos->next; //插入之 temp->next=position; pre_pos->next=temp; work_count++; return 0; } return -1;//添加不成功 } void destory_work_queue() { work_queue_t * temp; if(work_count!=0) { while(work_queue->head) { temp=work_queue->head; work_queue->head=work_queue->head->next; delete temp->elment; delete temp; } } } bool empty() { bool flage=false; if(work_count==0) flage=true; return flage; } //线程池的操作 //初始化线程池 void thread_pool(int init_threads_num) { pthread_mutex_init(&queue_lock,NULL);//初始化锁 if(pthread_cond_init(&pool_cond,NULL)!=0) return ; work_queue=init_work_queue();//工作队列 if(!work_queue) return ; max_thread=init_threads_num; idles=0; busy=0; to_exit=false; validate=true; } //销毁线程池和工作队列,条件变量,锁 void destroy_thread_pool() { pthread_mutex_lock(&queue_lock); //改变条件 to_exit=true; validate=false; //取消线程池中的所有线程 for(size_t i=0;i!=threads.size();++i) pthread_cancel(threads[i]); //销毁工作队列 destory_work_queue(); pthread_mutex_unlock(&queue_lock); //销毁锁和条件变量 pthread_mutex_destroy(&queue_lock); pthread_cond_destroy(&pool_cond); } int exec_task(task * new_task) { pthread_t tid; pthread_mutex_lock(&queue_lock); //将新任务添加至工作队列 if(add_tast(new_task)!=0) { pthread_mutex_unlock(&queue_lock); return -1; } pthread_cond_signal(&pool_cond);//工作队列中有任务了,唤醒一个阻塞线程 //是否新建线程,视条件而定 if(validate&&!to_exit&&(idles==0||(idles+busy)<max_thread)) { if(pthread_create(&tid,NULL,thread_rounter,NULL)!=0) { pthread_mutex_unlock(&queue_lock); return -1; } threads.push_back(tid);//记录线程id idles++;//多了一个空闲线程 pthread_mutex_unlock(&queue_lock); return 0; } pthread_mutex_unlock(&queue_lock); return 0; } void *thread_rounter(void *) { pthread_detach(pthread_self());//分离自己 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL); pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);//到达取消点处才取消线程 work_queue_t * work_item=NULL; for(;;)//去检查工作队列中是否有需要处理的工作项目 { pthread_mutex_lock(&queue_lock); while(validate&&!to_exit&&((work_item=remove_task())==NULL))//工作队列为空,则一直等待 pthread_cond_wait(&pool_cond,&queue_lock);//这里将会是一个取消点 pthread_mutex_unlock(&queue_lock); if(validate&&!to_exit&&work_item->elment->data) { pthread_mutex_lock(&queue_lock); busy++;//该线程忙 idles--; pthread_mutex_unlock(&queue_lock); work_item->elment->handler(work_item->elment->data);//处理函数调用 pthread_mutex_lock(&queue_lock); busy--; idles++; pthread_mutex_unlock(&queue_lock); //释放资源 delete work_item->elment; delete work_item; } } return NULL; }
测试结果:
先前的没有优先级与有优先级进行比较:
(1)同样都是线程池中最多10个线程,12个任务。结果如下:
有优先级:
I am task three
I am task four
I am task five
I am task six
I am task seven
I am task eight
I am task nine
I am task twltle
I am task eleven
I am task two
I am task one
I am task ten
无优先级:
I am task one
I am task two
I am task three
I am task four
I am task five
I am task six
I am task seven
I am task nine
I am task ten
I am task eleven
I am task twltle
I am task eight
(2)具有优先级的队列采用2个线程12个任务,
没有优先级的队列采用10个线程12个任务。
测试结果如下:
具有优先级:
I am task eight
I am task twltle(下面开始稳定)
I am task eleven
I am task ten
I am task nine
I am task seven
I am task six
I am task five
I am task four
I am task three
I am task two
I am task one
没有优先级:
I am task one
I am task two
I am task three
I am task four
I am task five
I am task six
I am task seven
I am task eight
I am task nine
I am task ten
I am task eleven
I am task twltle
测试表明:
优先级只是一个大概的,只有当线程池
稳定的时候才有效,即线程池中线程到达最大数目
之后在添加任务优先级发挥作用。