linux下模拟线程池

来源:互联网 发布:js设置css样式 编辑:程序博客网 时间:2024/05/30 04:57

     当需要利用线程大量处理任务时,使用线程池可以减小大量创建、销毁线程的开销,特别是任务处理时间短时更能节省系统资源。

     线程池的基本原理是在任务执行开始前,就预先创建一定数量的线程放入线程列表(链表,数组,队列等)中,创建这些线程都是处于休眠状态。当任务到来后,从线程池中选择一个空闲的线程,用此线程执行,如果无空闲的线程则创建新的线程来处理,并将些线程加入线程池。任务执行完成之后,将线程重新阻塞,等待下一次任务。当一定量的线程处于阻塞状态时,自动销毁线程池中的部分的线程

thread_pool.h

#ifndef __THREAD_POOL__#define __THREAD_POOL__typedef void *(*handle_fun)(void *arg);typedef struct{    uint32_t    min_th;      /*保持的最少线程数*/    uint32_t    cur_th;      /*线程池中当前线程数*/    uint32_t    max_th;      /*允许的最大线程数*/    uint32_t    free_th;        pthread_mutex_t pool_lock;        list_t      *threads;     /*list of threads*/    pthread_t   monitor_th;}thread_pool;int has_cap_to_process_task_queue(thread_pool *pool);int task_process(thread_pool *pool, process_fun fun, void *arg);thread_pool *thread_pool_create(uint32_t min, uint32_t max);#endif

thread_pool.c

/******************************************************************************  zgang     2013/9/10******************************************************************************/#include <stdio.h>#include <unistd.h>#include <string.h>#include <pthread.h>#include <signal.h>#include <stdlib.h>#include "hm_types.h"#include "hm_util.h"#include "thread_pool.h"typedef struct{    pthread_t       thread_id;    uint8_t         is_busy;    uint8_t         to_be_die;    pthread_cond_t  cond;    pthread_mutex_t lock;        handle_fun      proc;    void           *arg;        thread_pool    *pool;    listnode_t     *node;}thread_info;#define LOCK_POOL(_pool) \    pthread_mutex_lock(&_pool->pool_lock)#define UNLOCK_POOL(_pool) \    pthread_mutex_unlock(&_pool->pool_lock)static void *work_thread(void *arg){    thread_info *info = (thread_info *)arg;    thread_pool *pool = info->pool;    listnode_t  *node = info->node;    list_t      *list = pool->threads;    while (1)    {        if (info->to_be_die)        {            break;        }        if (info->proc)        {            info->proc(info->arg);            info->is_busy = FALSE;            info->proc = NULL;            LOCK_POOL(pool);            node->data = info;            node->prev = list->tail;            node->next = NULL;            if (list->head == NULL)                list->head = node;            else                list->tail->next = node;            list->tail = node;            list->count++;            UNLOCK_POOL(pool);        }        pthread_mutex_lock(&info->lock);        pthread_cond_wait(&info->cond, &info->lock);        pthread_mutex_unlock(&info->lock);    }    }/*从线程池中取出空闲线程*/static thread_info  *get_idle_thread(thread_pool *pool){    thread_info *idle = NULL;    listnode_t  *node = NULL;    list_t *idle_list = NULL;    LOCK_POOL(pool);    idle_list = pool->threads;    if (idle_list->head == NULL || idle_list->count == 0)    {        UNLOCK_POOL(pool);        return NULL;    }    node = idle_list->head;    idle_list->head = node->next;        if (!idle_list->head)        idle_list->tail = NULL;    else        idle_list->head->prev = NULL;            idle_list->count--;        idle = node->data;    idle->is_busy = TRUE;    UNLOCK_POOL(pool);        return idle;}/*向线程池添加新的线程*/static thread_info *add_new_thread_to_pool(thread_pool *pool){    thread_info *thread = NULL;    LOCK_POOL(pool);    if (pool->cur_th >= pool->max_th)    {        dpf("%d >= %d", pool->cur_th, pool->max_th);        UNLOCK_POOL(pool);        sleep(30);        return NULL;    }    UNLOCK_POOL(pool);        thread = (thread_info *)malloc(sizeof(thread_info));    if (thread == NULL)    {        dpf("memory error!");        sleep(30);        return NULL;    }    memset(thread, 0, sizeof(thread_info));    pthread_cond_init(&thread->cond, NULL);    pthread_mutex_init(&thread->lock, NULL);    thread->proc = NULL;    thread->arg = NULL;    LOCK_POOL(pool);    thread->pool = pool;    thread->node = listnode_add(pool->threads, (void *)thread);    UNLOCK_POOL(pool);        if (pthread_create(&thread->thread_id, NULL, work_thread, thread) != 0)    {        LOCK_POOL(pool);        listnode_delete(pool->threads, thread);        UNLOCK_POOL(pool);        dpf("create thread error!");        sleep(30);        return NULL;    }    LOCK_POOL(pool);    pool->cur_th++;    UNLOCK_POOL(pool);    usleep(10000);    return thread;}int task_process(thread_pool *pool, handle_fun fun, void *arg){    thread_info *thread = NULL;    thread = get_idle_thread(pool);    if (thread)      {        thread->is_busy = TRUE;        thread->proc = fun;        thread->arg = arg;        pthread_cond_signal(&thread->cond);  /*唤醒线程*/        return 0;    }    else        /*线程池中无空闲线程,则创建新的线程*/    {        thread = add_new_thread_to_pool(pool);        if (!thread)        {            thread->is_busy = TRUE;            thread->proc = fun;            thread->arg = arg;            pthread_cond_signal(&thread->cond);            return 0;        }        else        {            dpf("can't handle");            return 1;        }    }}int is_too_many_idle_threads(thread_pool *pool){    LOCK_POOL(pool);    if (pool->cur_th <= pool->min_th)    {        UNLOCK_POOL(pool);        return 0;    }    float free_thld = (float)(pool->threads->count) / pool->cur_th;    UNLOCK_POOL(pool);    if (free_thld > 0.5)    // if half of threads are idle, kill some of them        return 1;    else        return 0;}/*从线程池中删除进程*/void delete_thread_from_pool(thread_pool *pool){    thread_info *pthread = NULL;    LOCK_POOL(pool);    if (pool->cur_th <= pool->min_th)    {        UNLOCK_POOL(pool);        return;    }    UNLOCK_POOL(pool);        pthread = get_idle_thread(pool);    if (pthread)    {        LOCK_POOL(pool);        pool->cur_th--;        UNLOCK_POOL(pool);                pthread->to_be_die = TRUE;        while (!pthread->to_be_die)        {            usleep(1000);            pthread->to_be_die = TRUE;        }        pthread_cond_signal(&pthread->cond);        usleep(10000);                pthread_mutex_destroy(&pthread->lock);        pthread_cond_destroy(&pthread->cond);        free(pthread->node);        free(pthread);    }}/*监测线程数量*/static void *monitor_thread(void *arg){    thread_pool *pool = (thread_pool *)arg;        while (1)    {        while (is_too_many_idle_threads(pool)) /*空闲线程过多,杀掉一部分*/        {            delete_thread_from_pool(pool);        }        sleep(15);    }    return NULL;}int has_cap_to_process_task_queue(thread_pool *pool){    int rt = 0;    LOCK_POOL(pool);    rt = pool->threads->count;    if (rt)    {        UNLOCK_POOL(pool);        return 1;    }    else if (pool->cur_th < pool->max_th)    {        UNLOCK_POOL(pool);        return 1;    }    else    {        UNLOCK_POOL(pool);        return 0;    }}static void free_thread_info(void *p){    free(p);}thread_pool *thread_pool_create(uint32_t min, uint32_t max){    int i = 0;    thread_pool *pool = NULL;    thread_info *thread = NULL;        pool = (thread_pool *)malloc(sizeof(thread_pool));    if (pool == NULL)    {        return NULL;    }    memset(pool, 0, sizeof(pool));    pool->min_th = min;    pool->max_th = max;    pool->cur_th = min;    pthread_mutex_init(&pool->pool_lock, NULL);    pool->threads = list_new();    pool->threads->del = free_thread_info;    for (i = 0; i < min; i++)    {        thread = (thread_info *)malloc(sizeof(thread_info));        if (thread == NULL)        {                        list_delete(pool->threads);            free(pool);            return NULL;        }        memset(thread, 0, sizeof(thread_info));        pthread_cond_init(&thread->cond, NULL);        pthread_mutex_init(&thread->lock, NULL);        thread->proc = NULL;        thread->arg = NULL;        thread->pool = pool;        thread->node = listnode_add(pool->threads, (void *)thread);        if (pthread_create(&thread->thread_id, NULL, work_thread, thread) != 0)        {            list_delete(pool->threads);            return NULL;        }        pthread_detach(thread->thread_id);        usleep(50000);    }        if (pthread_create(&pool->monitor_th, NULL, monitor_thread, pool) != 0)    {        list_delete(pool->threads);        return NULL;    }        usleep(1000);    return pool;}


list.c

typedef struct listnode{    struct listnode *next;    struct listnode *prev;    void *data;}listnode_t;typedef void (*list_del_f)(void *val);typedef struct list{    listnode_t *head;    listnode_t *tail;    uint32_t    count;    list_del_f  del;}list_t;void list_delete(list_t *list){    listnode_t *node = NULL;    listnode_t *next = NULL;    for (node = list->head; node; node = node->next)    {        if (list->del)        {            (*list->del)(node->data);        }        free(node);    }    free(list);}list_t *list_new(){    list_t *new = NULL;    new = malloc(sizeof(list_t));    memset(new, 0, sizeof(list_t));    return new;}listnode_t *listnode_new(){    listnode_t *node = NULL;    node = (listnode_t *)malloc(sizeof(listnode_t));    if (node == NULL)        return NULL;    memset(node, 0, sizeof(listnode_t));    return node;}listnode_t * listnode_add(list_t *list, void *val){    listnode_t *node = NULL;    node = listnode_new();    if (node == NULL)        return NULL;    node->prev = list->tail;    node->data = val;    if (list->head == NULL)        list->head = node;    else        list->tail->next = node;    list->tail = node;    list->count++;    return node;}void listnode_delete(list_t *list, void *val){    listnode_t *node = NULL;    for (node = list->head; node; node = node->next)    {        if (node->data == val)        {            if (node->prev)                node->prev->next = node->next;            else                list->head = node->next;            if (node->next)                node->next->prev = node->prev;            else                list->tail = node->prev;            list->count--;            free(node);            break;        }    }}