线程池实现

来源:互联网 发布:淘宝卖家买家一个账号 编辑:程序博客网 时间:2024/06/16 22:27

线程池实现,

在一个源码的基础上调试运行的。已调通并成功运行。

注释相对完整,非常好理解

#ifdef DEBUG#define dprint(x) printf(x)#define dprintf(x,y) printf(x,y)#else#define dprint(x) #define dprintf(x,y)#endif#include #include #include #include #include typedef void* (*FUNC)(void* arg);static int thpool_keepalive = 1;pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*work队列中的job节点*/typedef struct _job_t{FUNC function;   //函数指针void* arg;       //函数参数struct _job_t* prev;  //指向上一个节点struct _job_t* next;  //指向下一个节点}thpool_job_t;/*work队列*/typedef struct _thpool_jobqueue{thpool_job_t* head;      //work队列头指针thpool_job_t* tail;//work队列尾指针int jobN;//work队列任务数sem_t* queueSem;//work队列信号量}thpool_jobqueue;/*线程池*/typedef struct _thpool_t{pthread_t* threads;        //线程指针int threadsN;              //线程数thpool_jobqueue* jobqueue; //指向work队列指针}thpool_t;//===============================================function==============================//work队列中的jobqueue初始化int thpool_jobqueue_init(thpool_t* thpool){//为work队列指针分配内存thpool->jobqueue = (thpool_jobqueue *)malloc( sizeof( thpool_jobqueue ));if(thpool->jobqueue == NULL){printf("malloc for jobqueue in thpool failed!\n");return -1;}thpool->jobqueue->head = NULL;thpool->jobqueue->tail = NULL;thpool->jobqueue->jobN = 0;//为work队列的信号量申请内存thpool->jobqueue->queueSem = (sem_t *)malloc(sizeof(sem_t));//初始化work队列的信号量sem_init( sem_t* _sem, int _pshared, unsigned int _value);sem_init(thpool->jobqueue->queueSem,0,1);return 0;}thpool_job_t* thpool_jobqueue_peek(thpool_t* thpool)     //取work队列中的job返回{return thpool->jobqueue->tail;}int thpool_jobqueue_removelast(thpool_t* thpool)          //删除work队列中的job节点,当此节点被成功peek和获取后{dprint("remove last job begin\n");if( NULL == thpool )return -1;thpool_job_t* temp;temp = thpool->jobqueue->tail;switch( thpool->jobqueue->jobN ){case 0:return -1;case 1:thpool->jobqueue->head = NULL;thpool->jobqueue->tail = NULL;break;default:temp->prev->next = NULL;thpool->jobqueue->tail = temp->prev;}thpool->jobqueue->jobN--;dprint("remove the last job success\n");return 0 ;}//pthread_create()中循环调用的函数pthread_init中void thpool_thread_do(thpool_t* thpool)                //线程池中线程执行work队列中的job{dprintf("thread code:%d\n", pthread_self());dprint("thpool_thread_do\n");while(thpool_keepalive == 1)                 //线程池可用{dprint("thpool_keepalive == 1\n");//等待线程池中work队列中的信号量post信号,信号量=0时挂起//int flag = sem_trywait(thpool->jobqueue->queueSem);dprintf("sem_trywait return : %d\n",flag);if( sem_wait(thpool->jobqueue->queueSem) ){dprint("keepalive == 1, sem_wait()\n");perror("thpool_thread_do():Waiting for Sem from workqueue");exit(1);}if(thpool_keepalive){FUNC function;void* arg_buff;//用来获取work队列中的jobthpool_job_t* job_p;dprint("before mutex\n");if(0 == thpool->jobqueue->jobN )                              return;pthread_mutex_lock(&mutex);         //控制取队列线程互斥job_p = thpool_jobqueue_peek( thpool );  //获取thpool进程池中work队列的job出队列dprintf("get the job: the last num:%d\n",thpool->jobqueue->jobN);if(-1 == thpool_jobqueue_removelast( thpool ))  return;function = job_p->function;arg_buff = job_p->arg;//if(thpool_jobqueue_removelast( thpool ))  //return;//free(job_p);dprint("thpool_keepalive == 1 and get out the func out \n");pthread_mutex_unlock(&mutex);//sleep(3);//printf("thread : %u get function!\n",pthread_self());function( arg_buff );        //执行job队列中的FUNC//pthread_mutex_unlock(&mutex);//printf("thread: %u finish function!\n",pthread_self());dprint("function running ...\n");free(job_p);}else{return;}}return;}//线程池initthpool_t* thpool_init(int threadN){thpool_t* thpool;if( !threadN || threadN <1 )threadN = 1;//分配线程池内存thpool = (thpool_t*) malloc(sizeof(thpool_t));if( thpool == NULL){printf("malloc thpoool error!\n");return NULL;}//设置线程数thpool->threadsN = threadN;//为线程池中的线程分配内存thpool->threads = (pthread_t*)malloc(threadN * sizeof(pthread_t));if(thpool->threads == NULL){printf("malloc threads error!\n");return NULL;}if(thpool_jobqueue_init(thpool))return NULL;//创建线程for(int i = 0 ; i < thpool->threadsN ; i++){pthread_create( &(thpool->threads[i]) , NULL , thpool_thread_do ,(void *)thpool );}dprint("pthreadPool init success!\n");return thpool;}//======================================================================================================================//将job加入work队列中void thpool_jobqueue_add( thpool_t* thpool , thpool_job_t* newjob_p){newjob_p->next = NULL;newjob_p->prev = NULL;thpool_job_t* temp;temp = thpool->jobqueue->head;switch( thpool->jobqueue->jobN )                 //判断是否是入队列第一个节点{case 0:thpool->jobqueue->head = newjob_p;thpool->jobqueue->tail = newjob_p;break;default:temp->prev = newjob_p;newjob_p->next = temp;thpool->jobqueue->head = newjob_p;}(thpool->jobqueue->jobN)++;sem_post( thpool->jobqueue->queueSem );        //发送有job需要线程执行的信号量int reval;sem_getvalue( thpool->jobqueue->queueSem , &reval);dprintf(" add job to queue successful,getvalue from sem_getvalue:%d\n " , reval );return;}//向线程池中加入jobint thpool_add_work( thpool_t* thpool , void* (*function_p)(void) , void* arg_p){thpool_job_t* newjob;newjob = ( thpool_job_t* )malloc( sizeof(thpool_job_t) );      //为新的job节点申请内存if( NULL == newjob ){fprintf(stderr,"thpool_add_work(): Could not allocate memory for new job!\n");exit(1);}newjob->function = function_p;newjob->arg = arg_p;pthread_mutex_lock( &mutex );              //为work队列加job的动作加锁thpool_jobqueue_add( thpool, newjob );pthread_mutex_unlock( &mutex );return 0;}//======================================================== Destory ======================================void thpool_jobqueue_empty( thpool_t* thpool ){thpool_job_t* temp;temp = thpool->jobqueue->tail;while( thpool->jobqueue->jobN ){thpool->jobqueue->tail = temp->prev;free( temp );temp = thpool->jobqueue->tail;( thpool->jobqueue->jobN )--;}thpool->jobqueue->head = NULL;thpool->jobqueue->tail = NULL;}void thpool_destory( thpool_t* thpool ){int i,reval;//thpool_keepalive = 0;      //将线程池置为不可用dprintf("destory!threads:%d\n", thpool->threadsN);for( i = 0 ; i < thpool->threadsN ; i++ ){if( sem_post( thpool->jobqueue->queueSem ) )    //有线程阻塞在这个信号量上thpool不能销毁(线程等待job)fprintf( stderr, "thpool_destory(): Could not bypass sem_wait()\n");}if( sem_post( thpool->jobqueue->queueSem ) != 0 ){fprintf( stderr , "thpool_destory(): Could not destory semaphore\n" );}for( i = 0 ; i < thpool->threadsN ; i++ ){dprintf("thread:%u\n", thpool->threads[i] );pthread_join( thpool->threads[i] , NULL );       //防止pthread_create()函数造成的内存泄漏,接手所有线程的资源,等到线程结束后释放}thpool_keepalive = 0;      //将线程池置为不可用thpool_jobqueue_empty( thpool );        //销毁进程池中的work队列free( thpool->threads );free( thpool->jobqueue->queueSem );free( thpool->jobqueue );free( thpool );}//============================================================================== Main =======================================void* task1(){//pthread_mutex_lock(&mutex);printf("# Thread working: %u\n" , (int)pthread_self() );sleep(3);printf("   Task 1 runnning...\n");//pthread_mutex_unlock(&mutex);}/*  task libuary */void* task2(int a){//pthread_mutex_lock(&mutex);printf("# Thread working: %u\n" , (int)pthread_self() );sleep(3);printf( "   Task %d running.. \n ", a );//pthread_mutex_unlock(&mutex);}int main(){printf("+++++++++++++++++++++++++++++++++\n");thpool_t* thpool;printf(" Creating a threadPool with 5 threads\n");thpool = thpool_init(5);for(int j = 0 ; j < thpool->threadsN ; j++){printf("The %d thread pid:%d\n" , j , thpool->threads[j] );}//wait(NULL);   //sleep(5); printf("Adding 10 group of jobs to threadPool...\n");for ( int i =0 ; i<10 ; i++ ){thpool_add_work(thpool , (void*)task1 , NULL);thpool_add_work(thpool , (void*)task2 , (void*)i );dprint("add two tasks!\n");}printf("add jobs finish");printf(" End! Kill the threadPool!\n");thpool_destory( thpool );}


原创粉丝点击