Linux中實現線程池

爲了實現高併發服務器,試驗了epoll+線程池的方式進行併發處理,效果並不理想。併發量主要受到線程池數目的約束,但是將線程池的實現記錄如下:

       參考網上相關文章,實現了線程池,方便以後使用。


/*threadpool.h*/

#ifndef __THREADPOOL_H__
#define __THREADPOOL_H__
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<unistd.h>
#include<assert.h>


/*線程池會維護一個任務鏈表,每個thread_worker接頭結構就是一個任務*/

typedef struct worker{
    /*回調函數,任務運行時會調用此函數*/
    void (*process)(void *arg);
    void *arg; /*回調參數*/
    struct worker *next;
}thread_worker;


/*線程池結構*/
typedef struct
{
    pthread_mutex_t queue_lock;
    pthread_cond_t queue_ready;

    /*鏈表結構*/
    thread_worker *queue_head;

    /*是否銷燬線程池*/
    int tp_stop;
    //線程數組
    pthread_t *threadid;  
    /*線程池中允許的活動線程數目*/
    int max_thread_num;
    /*當前等待隊列的任務數目*/
    int cur_queue_size;
}thread_pool;


//thread_pool *pool=NULL;


void pool_init(int max_thread_num);
/*向線程池的任務鏈表中加入一個任務*/
int pool_add_worker(void *(*process)(void *arg),void *arg);
int pool_destroy();

#endif

/*threadpool.c*/

#include "threadpool.h"

thread_pool *pool=NULL;

static void *thread_routine(void *arg);

void 
pool_init(int max_thread_num){
    pool=(thread_pool *)malloc(sizeof(thread_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->tp_stop=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){
    /*構造一個新任務*/
    thread_worker *newworker=
        (thread_worker *)malloc(sizeof(thread_worker));
    newworker->process=(void *)&process;
    newworker->arg=arg;
    newworker->next=NULL; 
    
    pthread_mutex_lock(&(pool->queue_lock));
    
    /*將任務加入等待隊列中*/
    thread_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_destroy(){
    if(pool->tp_stop)
        return -1;/*防止兩次調用*/
    pool->tp_stop=1;

    /*喚醒所有等待線程,線程池要銷燬了*/
    pthread_cond_broadcast(&(pool->queue_ready));

    /*阻塞等待線程退出,否則就成殭屍線程了*/
    int i;
    for(i=0;i<pool->max_thread_num;i++){
        pthread_join(pool->threadid[i],NULL);
    } 
    free(pool->threadid);
    
    /*銷燬等待隊列*/
    thread_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);
    pool=NULL;
    
    return 0;
}


static void *
thread_routine(void *arg){
    printf("starting thread 0x%x\n",pthread_self());
    while(1){
        pthread_mutex_lock(&(pool->queue_lock));
        /*如果等待隊列爲0,並且不銷燬線程池,則處於阻塞狀態
         * */
        while(pool->cur_queue_size==0 && !pool->tp_stop){
            printf("thread 0x%x is waiting\n",pthread_self());
            pthread_cond_wait(&(pool->queue_ready),&(pool->queue_lock));
        }
        /*如果線程池要銷燬了*/
        if(pool->tp_stop){
            /*遇到break,continue,return等跳轉語句,千萬不要忘記先解鎖*/
            pthread_mutex_unlock(&(pool->queue_lock));
            printf("thread 0x%x will exit\n",pthread_self());
            pthread_exit(NULL);
        }
        
        printf ("thread 0x%x is starting to work\n", pthread_self());
    
        assert(pool->cur_queue_size!=0);
        assert(pool->queue_head!=NULL);

        /*等待隊列長度減去1,並卻出鏈表中的頭元素*/
        pool->cur_queue_size--;
        thread_worker *work=pool->queue_head;
        pool->queue_head=work->next;
        pthread_mutex_unlock(&(pool->queue_lock));

        /*調用回調函數,執行任務*/
        work->process(work->arg);
        free(work);
        work=NULL;
    }
    /*這一句話應該是不可達的*/
    pthread_exit(NULL);
}

相關文章:

Linux--線程編程

http://www.cnblogs.com/forstudy/archive/2012/04/05/2433853.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章