简易线程池

线程池学习路径:www.bilibili.com,侵联删。

1、线程池的设计

程序中,频繁地调用pthread_create函数创建线程,非常浪费时间,尤其在服务器端的时候,多线程的使用情况下频繁启用线程和释放线程资源,这样也会影响程序的运行效率。

我们可以先在服务器空闲的时候先创建多个线程,我们先在线程函数里面使用pthread_cond_wait将其休眠,有任务过来的时候使用pthread_cond_signal启用线程。

线程池需要下面的相关知识:

线程的相关api函数

条件变量

互斥锁(与条件变量结合使用)

任务队列(链队使用更方便)

队列相当于是一个共享变量,这些子线程会不断地取任务去执行,有任务出队有任务入队,同一个时刻只能有一个任务进行操作。条件变量用来控制线程的睡眠、启动和销毁时机。

2、c语言实现简易线程池

threadpool.h

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>

// queue node
typedef struct Task 
{
        void (*function)(void *arg);                                                                 
        void *arg;
        struct Task *next;
} Task;

typedef struct ThreadPool
{
        Task *queueFront;
        Task *queueRear;

        int num;

        pthread_t *threadID;

        pthread_mutex_t mutex;

        pthread_cond_t cond;

        // shutdown pool
        int shutdown;
} ThreadPool;

threadpool.c

#include "threadpool.h"

void *worker(void *arg)
{
        ThreadPool *pool = (ThreadPool *)arg;
        while (1) 
        {
                pthread_mutex_lock(&pool->mutex);

                // 如果任务队列为空,且线程池没有被关闭,线程睡眠
                while (pool->queueFront == pool->queueRear && pool->shutdown == 0)
                {
                        // 阻塞等待任务
                        pthread_cond_wait(&pool->cond, &pool->mutex);
                }

                if (pool->shutdown == 1) {
                        printf("--------------------debug8");                        
                        pthread_mutex_unlock(&pool->mutex);
                        printf("thread shutdown thread %ld exit ...\n", pthread_self());
                        pthread_exit((void *)0);
                }

                Task task;
                Task *t = pool->queueFront->next;
                task.function = t->function;
                task.arg = t->arg;
                pool->queueFront->next = t->next;
                free(t);

                if (pool->queueFront->next == NULL) {
                        pool->queueRear = pool->queueFront;
                }

                pthread_mutex_unlock(&pool->mutex);

                printf("thread %ld start working ...\n", pthread_self());
                task.function(task.arg);        // 函数指针调用函数
                printf("thread %ld end working ...\n", pthread_self());
        }
}

ThreadPool *create_thread_pool(int num)
{
        // printf("--------------------debug1");
        ThreadPool *pool = (ThreadPool *)malloc(sizeof(ThreadPool));
        if (pool == NULL) {
                printf("malloc threadpool memory failed\n");
                return NULL;
        }
        // printf("--------------------debug2");

        pool->queueFront = (Task *)malloc(sizeof(Task));
        if (pool->queueFront == NULL) {
                fprintf(stderr, "malloc Task failed\n");
                goto pfree;
                return NULL;
        }

        // printf("--------------------debug3");
        // pool->queueRear = pool->queueFront;
        pool->queueFront->next =  NULL;
        pool->queueRear = pool->queueFront;

        pool->num = num;
        // printf("--------------------debug4");

        // init threadid
        pool->threadID = (pthread_t *)malloc(sizeof(pthread_t) * num);
        if (pool->threadID == NULL) {
                fprintf(stderr, "malloc threadID failed\n");
                goto qfree;
                return NULL;
        }

        // printf("--------------------debug5");
        for (int i = 0; i < num; i++) {
                if (pthread_create(&pool->threadID[i], NULL, worker, pool) != 0)
                {
                        fprintf(stderr, "pthread_create threadID failed\n");
                        goto tfree;
                        return NULL;
                }
                pthread_detach(pool->threadID[i]);        // pthread detach
        }

        // printf("--------------------debug6");
        pthread_mutex_init(&pool->mutex, NULL);
        pthread_cond_init(&pool->cond, NULL);

        pool->shutdown = 0;        // 0: running 1: shutsown

        return pool;
pfree:
        free(pool);
        return 0;
qfree:
        free(pool->queueFront);
        free(pool);
        return 0;
tfree:
        free(pool->threadID);
        free(pool->queueFront);
        free(pool);
        return 0;
}

void taskfunction(void *arg)
{
        int num = *(int *)arg;
        printf("thread %ld is working num = %d ...\n", pthread_self(), num);

        sleep(1);

        free(arg);
        // return 0;
}

void thread_pool_add(ThreadPool *pool, void (*func)(void *), void *arg)
{
        pthread_mutex_lock(&pool->mutex);

        Task *t = (Task *)malloc(sizeof(Task));
        if (t == NULL) {
                fprintf(stderr, "malloc Task failure\n");
                return;
        }

        // 一个任务包含三个部分,线程函数,参数,指向下一个任务节点的指针
        t->function = func;
        t->arg = arg;
        t->next = NULL;
        
        pool->queueRear->next = t;
        pool->queueRear = t;
        pthread_mutex_unlock(&pool->mutex);

        pthread_cond_signal(&pool->cond);
}

void thread_pool_destroy(ThreadPool *pool)
{
        // 关闭线程池
        pool->shutdown = 1;

        printf("--------------------debug7");
        // 唤醒所有线程
        for (int i = 0; i < pool->num; i++) {
                pthread_cond_signal(&pool->cond);
        }

        // 释放线程号
        if (pool->threadID) {
                free(pool->threadID);
        }

        // 释放任务队列
        while (pool->queueFront->next)
        {
                Task *t = pool->queueFront->next;
                pool->queueFront->next = t->next;
                free(t);
        }

        free(pool->queueFront);

        // 释放互斥锁和条件变量
        pthread_mutex_destroy(&pool->mutex);
        pthread_cond_destroy(&pool->cond);

        // 释放线程池
        free(pool);
}

int main()
{
        ThreadPool *pool = create_thread_pool(10);
        if (pool == NULL) {
                printf("create thread pool failed\n");
                return -1;
        }

        printf("threadPool create success.\n");

        sleep(1);

        for (int i = 0; i < 50; i++) {
                int *n = (int *)malloc(sizeof(int));

                *n = i;

                // 将任务添加到任务队列,taskfunction任务函数
                thread_pool_add(pool, taskfunction, n);
        }
        sleep(6);

        thread_pool_destroy(pool);

        return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_58550520/article/details/129141628