Linux线程池

来源:互联网 发布:身高 知乎 编辑:程序博客网 时间:2024/05/21 08:45

/*解析:这段代码创建了三个线程,10个任务。线程池的结构是CThread_pool,任务的结构是worker,他们都是一个连表。
程序先用pool_init创建拉三个线程。然后每个线程执行函数thread_routine。thread_routine在运行到pthread_cond_wait(&(pool->queue_ready),&(pool->queue_lock));时,等待共享变量被激活;
当添加任务的函数pool_add_worker添加拉任务之后,运行到pthread_cond_signal(&(pool->queue_ready));激活等待的线程。它告诉线程,有任务拉,可以运行拉。然后thread_routine运行pthread_cond_wait(&(pool->queue_ready),&(pool->queue_lock));之后的代码。

*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <assert.h>
/*
*线程池里所有运行和等待的任务都是一个CThread_worker;由于所有任务都在连表里,所以是个连表结构
*/
typedef struct worker
{
        /*回调函数,任务运行时会调用此函数,注意也可声明成其他形式*/
        void *(*process)(void *arg);
        void *arg;
        struct worker *next;
}CThread_worker;
/**线程池结构*/
typedef struct
{
        pthread_mutex_t queue_lock;
        pthread_cond_t queue_ready;
       
        /*连表结构,线程池中的所有等待任务*/
        CThread_worker *queue_head;
        /*是否销毁线程池*/
        int shutdown;
        pthread_t *threadid;
        /*线程池中允许的活动线程数目*/
        int max_thread_num;
        /*当前等待列队的任务数目*/
        int cur_queue_size;
}CThread_pool;

int pool_add_worker(void*(*process)(void *arg),void *arg);
void *thread_routine(void *arg);

static CThread_pool *pool=NULL;//=(CThread_pool *)NULL;

void pool_init(int max_thread_num)
{
        pool=(CThread_pool*)malloc(sizeof(CThread_pool));
        pthread_mutex_init(&(pool->queue_lock),NULL);
        //初始化一个条件变量,他的第二个条件变量可以用来定义这个变量是在进程间使用还是进程内各个线程间使用。
        pthread_cond_init(&(pool->queue_ready),NULL);
        pool->queue_head=NULL;
        pool->max_thread_num=max_thread_num;
        pool->cur_queue_size=0;
        pool->shutdown=0;
        pool->threadid=(pthread_t*)malloc(max_thread_num*sizeof(pthread_t));
        int i=0;
        for(i=0;i<max_thread_num;i++)
        {
                pthread_create(&(pool->threadid[i]),NULL,thread_routine,NULL);
        }
}

/*向线程池中添加任物*/
int pool_add_worker(void *(*process)(void *arg),void *arg)
{
        printf("pool_add_worker:/n");
        /*构造一个新任务*/
        CThread_worker *newworker=(CThread_worker*)malloc(sizeof(CThread_worker));
        newworker->process=process;
        newworker->arg=arg;
        newworker->next=NULL;/*dont forget set it to null*/
        pthread_mutex_lock(&(pool->queue_lock));
        /*将任务加入到等待列队中*/
        CThread_worker* member=pool->queue_head;
        if(member!=NULL)
        {
                while(member->next!=NULL)
                        member = member->next;
                member->next=newworker;
        }
        else
        {
                pool->queue_head=newworker;
        }
       
        assert(pool->queue_head!=NULL);
       
        pool->cur_queue_size++;
        pthread_mutex_unlock(&(pool->queue_lock));        
        /*好了,等待列队中有任务拉,唤醒一个等待线程;注意如果所有线程都在忙碌,这句话没有任何作用*/
        pthread_cond_signal(&(pool->queue_ready));
        return 0;
}

/*销毁线程池,等待列队中的任务不会再被执行拉。但是正在运行的线程会一直把任务运行完后再推出*/
int pool_destory()
{
        if(pool->shutdown)
                return -1;/*防止两次调用*/
        pool->shutdown=1;
        /*唤醒所有等待的线程,线程池要销毁拉*/
        pthread_cond_broadcast(&(pool->queue_ready));

        /*阻塞等待线程退出,否则就成拉僵尸拉*/
        int i;
        for(i=0;i<pool->max_thread_num;i++)
        {
                printf("pool_destroy: thread %d/n",i);
                pthread_join(pool->threadid[i],NULL);//用来等待线程结束,这事一个阻塞函数
        }
        free(pool->threadid);
       
        /*销毁等待列队*/
        CThread_worker *head=NULL;
        while(pool->queue_head!=NULL)
        {
                head=pool->queue_head;
                pool->queue_head=pool->queue_head->next;
                free(head);
        }
        /*条件变量和互斥变量也别忘了销毁*/
        pthread_mutex_destroy(&(pool->queue_lock));
        pthread_cond_destroy(&(pool->queue_ready));
       
        free(pool);
        /*销毁后指针置NULL,good*/
        pool=NULL;
        return 0;        
}

void *thread_routine(void *arg)
{
        printf("starting thread 0x%ld/n",pthread_self());
        while(1)
        {
                pthread_mutex_lock(&(pool->queue_lock));
                 /*如果等待列队为0并且不销毁线程池,则处于阻塞状态;*注意pthread_cond_wait是一个原子操作,等待前会解锁,唤醒后会加锁*/
                while((pool->cur_queue_size==0)&&(!pool->shutdown))
                {
                        printf("thread 0x%ld is waiting/n",pthread_self());
                        pthread_cond_wait(&(pool->queue_ready),&(pool->queue_lock));
                }
                /*线程池要销毁拉*/
                if(pool->shutdown)
                {
                        /*遇到break,continue, return等语句跳转,别忘记现解锁*/
                        pthread_mutex_unlock(&(pool->queue_lock));
                        printf("thread 0x%x will exit/n",pthread_self());
                        pthread_exit(NULL);
                }
                printf("thread 0x%ld is starting to work/n",pthread_self());
               
                /*assert 是调试的好帮手*/
                assert(pool->cur_queue_size!=0);
                assert(pool->queue_head!=NULL);
               
                /*等待队列长度减去1,并取出联表中的头元素*/
                pool->cur_queue_size--;
                CThread_worker *worker=pool->queue_head;
                pool->queue_head=worker->next;
                pthread_mutex_unlock(&(pool->queue_lock));
               
                /*调用回调函数,执行任务*/
                printf("************/n");
                (*(worker->process))(worker->arg);
                free(worker);
                worker=NULL;
        }
        /*这一句应该是不可达的*/
        pthread_exit(NULL);
}

/*测试代码*/
void * myprocess(void *arg)
{
        printf("threadid is 0x%ld,working on task %d/n",pthread_self(),*(int*)arg);
        sleep(1);/*休息一秒,延长任务的执行时间*/
        return NULL;        
}
int main(int argc,char** argv)
{
        pool_init(3);/*线程池中最多三个活动线程*/
        /*连续向池中投入10个任务*/
        int *workingnum = (int*)malloc(sizeof(int)*10);
        int i;
        for(i=0;i<10;i++)
        {
                printf("main:while %d/n",i);
                workingnum[i]=i;
                pool_add_worker(myprocess,&workingnum[i]);
        }
               printf("/nSleep 5 sec to wait all thread work!/n ");
        /*等待所有任务完成*/
        sleep(5);
        /*销毁线程池*/
        printf("/n销毁线程池/n");
        pool_destory();
       
        free(workingnum);
        return 0;
       
}
/*输出*/
/*
starting thread 0x140353963693824
starting thread 0x140353955301120
main:while 0
starting thread 0x140353946908416
thread 0x140353963693824 is waiting
pool_add_worker:
main:while 1
pool_add_worker:
thread 0x140353963693824 is starting to work
************
threadid is 0x140353963693824,working on task 0
thread 0x140353946908416 is waiting
thread 0x140353955301120 is starting to work
************
threadid is 0x140353955301120,working on task 1
main:while 2
pool_add_worker:
thread 0x140353946908416 is waiting
main:while 3
pool_add_worker:
thread 0x140353946908416 is starting to work
************
threadid is 0x140353946908416,working on task 2
main:while 4
pool_add_worker:
main:while 5
pool_add_worker:
main:while 6
pool_add_worker:
main:while 7
pool_add_worker:
main:while 8
pool_add_worker:
main:while 9
pool_add_worker:

Sleep 5 sec to wait all thread work!
 thread 0x140353963693824 is starting to work
************
threadid is 0x140353963693824,working on task 3
thread 0x140353955301120 is starting to work
************
thread 0x140353946908416 is starting to work
************
threadid is 0x140353946908416,working on task 5
threadid is 0x140353955301120,working on task 4
thread 0x140353963693824 is starting to work
************
threadid is 0x140353963693824,working on task 6
thread 0x140353946908416 is starting to work
************
thread 0x140353955301120 is starting to work
************
threadid is 0x140353955301120,working on task 8
threadid is 0x140353946908416,working on task 7
thread 0x140353963693824 is starting to work
************
threadid is 0x140353963693824,working on task 9
thread 0x140353946908416 is waiting
thread 0x140353955301120 is waiting
thread 0x140353963693824 is waiting

销毁线程池
pool_destroy: thread 0
thread 0xb325f700 will exit
thread 0xb3a60700 will exit
thread 0xb4261700 will exit
pool_destroy: thread 1
pool_destroy: thread 2
*/

原创粉丝点击