线程池实现

线程池实现,

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

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

#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队列中的job thpool_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; } //线程池init thpool_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; } //向线程池中加入job int 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 ); } 
       
      
      
     
     
    
    
   
   


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值