c语言简单线程池实现

#include 
#include 
#include
#include 
#include

//定义一个任务结构体
typedef struct task_t
{
    void (*function)(void* arg); //任务函数指针
    void* arg; //任务函数参数指针变量
    struct task_t* next; //指向下一个任务节点指针
}task_t; //typedef重命名

//定义线程池结构体
typedef struct thread_pool
{

    int thread_count;     //线程池的线程数量
    int queue_size;       //任务队列的最大长度,最多有多少任务要处理
    pthread_t* threads;   //指向线程数组的指针;在这里存放数组
    task_t* head;         //指向任务队列头部的指针
    task_t* tail;         //指向任务队列尾部的指针
    pthread_mutex_t lock; //互斥锁,用于保护任务队列
    pthread_cond_t notify; //条件变量,用于通知空闲线程有新的任务
    bool shutdown;         //是否关闭线程

}thread_pool_t;


void* thread_pool_worker(void* arg);

/* 初始化线程池
*1:线程池指针
*2:线程数量
*3:任务数量
*/
bool thread_pool_init(thread_pool_t* pool, int thread_count, int queue_size)
{
    pool->thread_count = 0;           //当前还未创建线程,所有数量为0
    pool->queue_size = queue_size;    //任务个数
    pool->threads = (pthread_t*)malloc(thread_count * sizeof(pthread_t));
    if (pool->threads == NULL)
    {
        printf("malloc failed");
        return false;
    }
    
    //任务队列头尾指针初始化为空
    pool->head = NULL;
    pool->tail = NULL;
    
    //线程锁和条件锁初始化
    pthread_mutex_init(&pool->lock, NULL);
    pthread_cond_init(&pool->notify,NULL);

    //关闭线程
    pool->shutdown = false;

    //创建工作线程
    for (int i = 0; i < thread_count; i++)
    {
        if (pthread_create(&pool->threads[i], NULL, thread_pool_worker, (void*)pool) != 0)
        {
            printf("pthread create failed");
            return false;
        }
        pool->thread_count++;
    }
    return true;
}

/*线程工作函数,它负责从任务队列中取出任务并执行*/
void* thread_pool_worker(void* arg)
{
    printf("i am ready for work\n");
    thread_pool_t* pool = (thread_pool_t*)arg;
    while(true)
    {
        //保护任务队列,同一时刻只能有一个线程访问修改任务队列
        pthread_mutex_lock(&pool->lock); 
        //判断任务队列是否为空,线程池是否关闭
        while ((pool->head == NULL) && (!pool->shutdown))
        {
            //如果任务队列为空,线程池没有关闭,等待新任务到来
            /*当任务队列为空,且线程池未关闭,线程会进入等待状态,即调用pthread_cond_wait函数等待
            条件变量的通知,当有任务时,会调用pthread_cond_signal()或者pthread_cond_broadcast()函数
            发送通知*/
            /*这里会释放pool->lock锁,让其他线程持有,防止阻塞在这里*/
            printf("==================_pthread_cond_wait start_======================\n");
            pthread_cond_wait(&pool->notify,&pool->lock);
            printf("==================_pthread_cond_wait end_======================\n");
        }
        printf("pool->shutdown = %d\n", pool->shutdown);
        if (pool->shutdown)
        {
            pthread_mutex_unlock(&pool->lock);
            pthread_exit(NULL);
        }
        printf("while down\n");
       //从任务队列中取出第一个任务
        task_t* task = pool->head;
        if (pool->head == pool->tail)
        {
            pool->head = pool->tail = NULL;
        }
        else
        {
            pool->head = task->next;
        }
        pthread_mutex_unlock(&pool->lock);
        printf("=================_I am going to work_====================\n");
        task->function(task->arg);
    }
}

//向线程池中添加任务
bool thread_pool_add_task(thread_pool_t* pool, void(*function)(void* arg), void* arg)
{
    if (pool->shutdown)
    {
        return false;
    }
    task_t* new_task = (task_t*)malloc(sizeof(task_t));
    if (new_task == NULL)
    {
        return false;
    }
    
    new_task->function = function;
    new_task->arg = arg;
    new_task->next = NULL;

    //将新任务添加到任务队列中,添加时要锁住任务队列
    pthread_mutex_lock(&pool->lock);
    if (pool->head == NULL)
    {
        pool->head = pool->tail = new_task;
    }
    else
    {
        pool->tail->next = new_task;
        pool->tail = new_task;
    }

    //如果有空闲的线程在等待,通知他们有新任务处理,即被pthread_cond_wait阻塞的线程
    if (pthread_cond_signal(&pool->notify) != 0) 
    {
        pthread_mutex_unlock(&pool->lock);
        return false;
    }

    pthread_mutex_unlock(&pool->lock);

    return true;
}

//销毁线程池
bool thread_pool_destroy(thread_pool_t * pool)
{
    pool->shutdown = true;

    //等待所有线程结束
    for (int i = 0; i < pool->thread_count; i++)
    {
        if (pthread_join(pool->threads[i], NULL) != 0)
        {
            return false;
        }
    }
 
    //销毁任务队列和互斥锁和条件变量
    task_t* current;
    while (pool->head != NULL)
    {
        current = pool->head;
        pool->head = pool->head->next;
        free(current);
    }

    pthread_mutex_destroy(&pool->lock);
    pthread_cond_destroy(&pool->notify);

    free(pool->threads);

    return true;
}

//定义任务函数
void task_function(void* arg)
{
    int task_number = *((int*)arg);
    pthread_t thread_id = pthread_self();
    printf("Task %d is being processed by pthread %lu\n", task_number, thread_id);
    sleep(1);
}


int main()
{
    thread_pool_t pool;
    int thread_count = 4;
    int queue_size = 10;

    if (!thread_pool_init(&pool, thread_count, queue_size))
    {
        printf("thread init failed\n");
        return 1;
    }
    
    int task_count = 20;
    for (int i = 0; i < task_count; i++)
    {
        int* task_number = (int*)malloc(sizeof(int));
        if (task_number == NULL)
        {
            return 1;
        }
        *task_number = i;
        bool add_result =  thread_pool_add_task(&pool,task_function,task_number);
        if (!add_result)
        {
            printf("Failed to add task %d to thread pool.\n", i);
            return 1;
        }
    }


    sleep(30);

    // 等待所有任务完成并销毁线程池
    bool destroy_result = thread_pool_destroy(&pool); 
    if (!destroy_result)
    {
        printf("Failed to destroy thread pool.\n");
        return 1;
    }
    return 0;
}

li@li:~$ &"warning: GDB: Failed to set controlling terminal: \344\270\215\345\205\201\350\256\270\347\232\204\346\223\215\344\275\234\n"
i am ready for work
==================_pthread_cond_wait start_======================
i am ready for work
==================_pthread_cond_wait start_======================
i am ready for work
==================_pthread_cond_wait start_======================
i am ready for work
==================_pthread_cond_wait start_======================
==================_pthread_cond_wait end_======================
pool->shutdown = 0
while down
=================_I am going to work_====================
Task 0 is being processed by pthread 140737345496832
==================_pthread_cond_wait end_======================
pool->shutdown = 0
while down
=================_I am going to work_====================
Task 1 is being processed by pthread 140737328711424
==================_pthread_cond_wait end_======================
pool->shutdown = 0
while down
=================_I am going to work_====================
Task 2 is being processed by pthread 140737320318720
==================_pthread_cond_wait end_======================
pool->shutdown = 0
while down
=================_I am going to work_====================
Task 3 is being processed by pthread 140737337104128
pool->shutdown = 0
while down
=================_I am going to work_====================
Task 4 is being processed by pthread 140737345496832
pool->shutdown = 0
while down
=================_I am going to work_====================
Task 5 is being processed by pthread 140737328711424
pool->shutdown = 0
while down
=================_I am going to work_====================
Task 6 is being processed by pthread 140737320318720
pool->shutdown = 0
while down
=================_I am going to work_====================
Task 7 is being processed by pthread 140737337104128
pool->shutdown = 0
while down
=================_I am going to work_====================
Task 8 is being processed by pthread 140737345496832
pool->shutdown = 0
while down
=================_I am going to work_====================
Task 9 is being processed by pthread 140737328711424
pool->shutdown = 0
while down
=================_I am going to work_====================
Task 10 is being processed by pthread 140737320318720
pool->shutdown = 0
while down
=================_I am going to work_====================
Task 11 is being processed by pthread 140737337104128
pool->shutdown = 0
while down
=================_I am going to work_====================
Task 12 is being processed by pthread 140737345496832
pool->shutdown = 0
while down
=================_I am going to work_====================
Task 13 is being processed by pthread 140737328711424
pool->shutdown = 0
while down
=================_I am going to work_====================
Task 14 is being processed by pthread 140737320318720
pool->shutdown = 0
while down
=================_I am going to work_====================
Task 15 is being processed by pthread 140737337104128
pool->shutdown = 0
while down
=================_I am going to work_====================
Task 16 is being processed by pthread 140737345496832
pool->shutdown = 0
while down
=================_I am going to work_====================
Task 17 is being processed by pthread 140737328711424
pool->shutdown = 0
while down
=================_I am going to work_====================
Task 18 is being processed by pthread 140737320318720
pool->shutdown = 0
while down
=================_I am going to work_====================
Task 19 is being processed by pthread 140737337104128
==================_pthread_cond_wait start_======================
==================_pthread_cond_wait start_======================
==================_pthread_cond_wait start_======================
==================_pthread_cond_wait start_======================

你可能感兴趣的:(多线程学习,c语言,开发语言)