线程池实现原理及案列

来源:互联网 发布:ccdd数据库 编辑:程序博客网 时间:2024/05/29 04:15

一、原理图

这里写图片描述

我们都知道,线程池和多线程的区别就是一个是业务来了动态地去产生线程,一个是把线程事先产生出来放到一个池子中,当要使用线程的时候,从池子中拿出来,当用完后,再把线程放回池子中,但它远远没有这么简单。首先看看原理图,当客户端请求连接时,服务器监听到之后会将其放入到任务队列中,线程再从任务队列中拿走任务,这是两个典型的生产者消费者模型。对于后面的线程池来说,一开始初始化的时候,根据设计的不同,回去限定线程的最大个数,最小个数,初始化多少个等等。

例如:

int min_thr_num;                    /*线程组内默认最小线程数*/int max_thr_num;                    /*线程组内默认最大线程数*/int live_thr_num;                   /*当前存活线程个数*/int busy_thr_num;                   /*忙状态线程个数*/int wait_exit_thr_num;              /*要销毁的线程个数*/

监控线程的任务也是简单明了,一般情况就是根据一定的算法去动态的产生于销毁线程。

例如:

GetAllNum表示获取线程池所有的线程数,m_iInitNum 表示初始化的线程数量,iAvailNum 工作的线程数,m_iMaxNum最大线程数,m_iAvailHigh工作线程的最高数量 if(iAvailNum < m_iAvailLow)  {    if(GetAllNum() + m_iInitNum - iAvailNum < m_iMaxNum)    {        CreateIdleThread(m_iInitNum - iAvailNum);    }    else    {      CreateIdleThread(m_iMaxNum - GetAllNum());    }  }  else if(iAvailNum > m_iAvailHigh)  {      DeleteIdleThread(1);  }

void *adjust_thread(void *threadpool){   int i;    threadpool_t *pool = (threadpool_t *)threadpool;    while (!pool->shutdown) {    sleep(DEFAULT_TIME);                                    /*延时10秒*/    pthread_mutex_lock(&(pool->lock));    int queue_size = pool->queue_size;    int live_thr_num = pool->live_thr_num;    pthread_mutex_unlock(&(pool->lock));    pthread_mutex_lock(&(pool->thread_counter));    int busy_thr_num = pool->busy_thr_num;    pthread_mutex_unlock(&(pool->thread_counter));    /*任务数大于最小线程池个数并且存活的线程数少于最大线程个数时,创建新线程*/    if (queue_size >= MIN_WAIT_TASK_NUM && live_thr_num < pool->max_thr_num) {        pthread_mutex_lock(&(pool->lock));        int add = 0;        /*一次增加DEFAULT_THREAD个线程*/        for (i = 0; i < pool->max_thr_num && add < DEFAULT_THREAD_VARY                && pool->live_thr_num < pool->max_thr_num; i++) {            if (pool->threads[i] == 0 || !is_thread_alive(pool->threads[i])) {                pthread_create(&(pool->threads[i]), NULL, threadpool_thread, (void *)pool);                add++;                pool->live_thr_num++;            }        }        pthread_mutex_unlock(&(pool->lock));    }    /*销毁多余的空闲线程*/    if ((busy_thr_num * 2) < live_thr_num && live_thr_num > pool->min_thr_num) {        /*一次销毁DEFAULT_THREAD个线程*/        pthread_mutex_lock(&(pool->lock));        pool->wait_exit_thr_num = DEFAULT_THREAD_VARY;        pthread_mutex_unlock(&(pool->lock));        for (i = 0; i < DEFAULT_THREAD_VARY; i++) {            /*通知处在空闲状态的线程*/            pthread_cond_signal(&(pool->queue_not_empty));        }    }}  return NULL; }

完整线程池代码

#include <stdlib.h>#include <pthread.h>#include <unistd.h>#include <assert.h>#include <stdio.h>#include <string.h>#include <signal.h>#include <errno.h>#include "threadpool.h"#define DEFAULT_TIME 10                 #define MIN_WAIT_TASK_NUM 10          #define DEFAULT_THREAD_VARY 10         #define true 1#define false 0typedef struct {    void *(*function)(void *);            void *arg;                        } threadpool_task_t;                   struct threadpool_t {    pthread_mutex_t lock;                  pthread_mutex_t thread_counter;         pthread_cond_t queue_not_full;         pthread_cond_t queue_not_empty;         pthread_t *threads;                     pthread_t adjust_tid;                 threadpool_task_t *task_queue;         int min_thr_num;                      int max_thr_num;                        int live_thr_num;                      int busy_thr_num;                      int wait_exit_thr_num;                int queue_front;                      int queue_rear;                         int queue_size;                        int queue_max_size;                    int shutdown;                     };void *threadpool_thread(void *threadpool);void *adjust_thread(void *threadpool);int is_thread_alive(pthread_t tid);int threadpool_free(threadpool_t *pool);threadpool_t *threadpool_create(int min_thr_num, int max_thr_num, int queue_max_size){    int i;    threadpool_t *pool = NULL;    do{        if((pool = (threadpool_t *)malloc(sizeof(threadpool_t))) == NULL) {            printf("malloc threadpool fail");            break;                }        pool->min_thr_num = min_thr_num;        pool->max_thr_num = max_thr_num;        pool->busy_thr_num = 0;        pool->live_thr_num = min_thr_num;        pool->queue_size = 0;        pool->queue_max_size = queue_max_size;        pool->queue_front = 0;        pool->queue_rear = 0;        pool->shutdown = false;        pool->threads = (pthread_t *)malloc(sizeof(pthread_t)*max_thr_num);        if (pool->threads == NULL) {            printf("malloc threads fail");            break;        }        memset(pool->threads, 0, sizeof(pthread_t)*max_thr_num);        pool->task_queue = (threadpool_task_t *)malloc(sizeof(threadpool_task_t)*queue_max_size);        if (pool->task_queue == NULL) {            printf("malloc task_queue fail");            break;        }        if (pthread_mutex_init(&(pool->lock), NULL) != 0                || pthread_mutex_init(&(pool->thread_counter), NULL) != 0                || pthread_cond_init(&(pool->queue_not_empty), NULL) != 0                || pthread_cond_init(&(pool->queue_not_full), NULL) != 0)        {            printf("init the lock or cond fail");            break;        }        for (i = 0; i < min_thr_num; i++) {            pthread_create(&(pool->threads[i]), NULL, threadpool_thread, (void *)pool);            printf("start thread 0x%x...\n", (unsigned int)pool->threads[i]);        }        pthread_create(&(pool->adjust_tid), NULL, adjust_thread, (void *)pool);        return pool;    } while (0);    threadpool_free(pool);        return NULL;}int threadpool_add(threadpool_t *pool, void*(*function)(void *arg), void *arg){    pthread_mutex_lock(&(pool->lock));    while ((pool->queue_size == pool->queue_max_size) && (!pool->shutdown)) {        pthread_cond_wait(&(pool->queue_not_full), &(pool->lock));    }    if (pool->shutdown) {        pthread_mutex_unlock(&(pool->lock));    }    if (pool->task_queue[pool->queue_rear].arg != NULL) {        free(pool->task_queue[pool->queue_rear].arg);        pool->task_queue[pool->queue_rear].arg = NULL;    }    pool->task_queue[pool->queue_rear].function = function;    pool->task_queue[pool->queue_rear].arg = arg;    pool->queue_rear = (pool->queue_rear + 1)%pool->queue_max_size;    pool->queue_size++;    pthread_cond_signal(&(pool->queue_not_empty));    pthread_mutex_unlock(&(pool->lock));    return 0;}void *threadpool_thread(void *threadpool){    threadpool_t *pool = (threadpool_t *)threadpool;    threadpool_task_t task;    while (true) {        pthread_mutex_lock(&(pool->lock));        while ((pool->queue_size == 0) && (!pool->shutdown)) {            printf("thread 0x%x is waiting\n", (unsigned int)pthread_self());            pthread_cond_wait(&(pool->queue_not_empty), &(pool->lock));            if (pool->wait_exit_thr_num > 0) {            if (pool->live_thr_num > pool->min_thr_num) {                    printf("thread 0x%x is exiting\n", (unsigned int)pthread_self());                    pool->live_thr_num--;                    pthread_mutex_unlock(&(pool->lock));                    pthread_exit(NULL);                }            }        }        if (pool->shutdown) {            pthread_mutex_unlock(&(pool->lock));            printf("thread 0x%x is exiting\n", (unsigned int)pthread_self());            pthread_exit(NULL);        }        task.function = pool->task_queue[pool->queue_front].function;        task.arg = pool->task_queue[pool->queue_front].arg;        pool->queue_front = (pool->queue_front + 1)%pool->queue_max_size;        pool->queue_size--;        pthread_cond_broadcast(&(pool->queue_not_full));        pthread_mutex_unlock(&(pool->lock));        printf("thread 0x%x start working\n", (unsigned int)pthread_self());        pthread_mutex_lock(&(pool->thread_counter));        pool->busy_thr_num++;                                               pthread_mutex_unlock(&(pool->thread_counter));        (*(task.function))(task.arg);                                       //task.function(task.arg);                                       printf("thread 0x%x end working\n", (unsigned int)pthread_self());        pthread_mutex_lock(&(pool->thread_counter));        pool->busy_thr_num--;                                               pthread_mutex_unlock(&(pool->thread_counter));    }    pthread_exit(NULL);    //return (NULL);}void *adjust_thread(void *threadpool){    int i;    threadpool_t *pool = (threadpool_t *)threadpool;    while (!pool->shutdown) {        sleep(DEFAULT_TIME);                                           pthread_mutex_lock(&(pool->lock));        int queue_size = pool->queue_size;        int live_thr_num = pool->live_thr_num;        pthread_mutex_unlock(&(pool->lock));        pthread_mutex_lock(&(pool->thread_counter));        int busy_thr_num = pool->busy_thr_num;        pthread_mutex_unlock(&(pool->thread_counter));        if (queue_size >= MIN_WAIT_TASK_NUM && live_thr_num < pool->max_thr_num) {            pthread_mutex_lock(&(pool->lock));            int add = 0;            for (i = 0; i < pool->max_thr_num && add < DEFAULT_THREAD_VARY                    && pool->live_thr_num < pool->max_thr_num; i++) {                if (pool->threads[i] == 0 || !is_thread_alive(pool->threads[i])) {                    pthread_create(&(pool->threads[i]), NULL, threadpool_thread, (void *)pool);                    add++;                    pool->live_thr_num++;                }            }            pthread_mutex_unlock(&(pool->lock));        }        if ((busy_thr_num * 2) < live_thr_num && live_thr_num > pool->min_thr_num) {            pthread_mutex_lock(&(pool->lock));            pool->wait_exit_thr_num = DEFAULT_THREAD_VARY;            pthread_mutex_unlock(&(pool->lock));            for (i = 0; i < DEFAULT_THREAD_VARY; i++) {                pthread_cond_signal(&(pool->queue_not_empty));            }        }    }    return NULL;}int threadpool_destroy(threadpool_t *pool){    int i;    if (pool == NULL) {        return -1;    }    pool->shutdown = true;    pthread_join(pool->adjust_tid, NULL);    for (i = 0; i < pool->live_thr_num; i++) {        pthread_cond_broadcast(&(pool->queue_not_empty));        pthread_join(pool->threads[i], NULL);    }    threadpool_free(pool);    return 0;}int threadpool_free(threadpool_t *pool){    if (pool == NULL) {        return -1;    }    if (pool->task_queue) {        free(pool->task_queue);    }    if (pool->threads) {        free(pool->threads);        pthread_mutex_lock(&(pool->lock));        pthread_mutex_destroy(&(pool->lock));        pthread_mutex_lock(&(pool->thread_counter));        pthread_mutex_destroy(&(pool->thread_counter));        pthread_cond_destroy(&(pool->queue_not_empty));        pthread_cond_destroy(&(pool->queue_not_full));    }    free(pool);    pool = NULL;    return 0;}int threadpool_all_threadnum(threadpool_t *pool){    int all_threadnum = -1;    pthread_mutex_lock(&(pool->lock));    all_threadnum = pool->live_thr_num;    pthread_mutex_unlock(&(pool->lock));    return all_threadnum;}int threadpool_busy_threadnum(threadpool_t *pool){    int busy_threadnum = -1;    pthread_mutex_lock(&(pool->thread_counter));    busy_threadnum = pool->busy_thr_num;    pthread_mutex_unlock(&(pool->thread_counter));    return busy_threadnum;}int is_thread_alive(pthread_t tid){    int kill_rc = pthread_kill(tid, 0);    if (kill_rc == ESRCH) {        return false;    }    return true;}
原创粉丝点击