C语言编写的线程池

SingleBiu/c_thread_pool: C语言编写的线程池

pool.h:

cpp 复制代码
/*
 * @Author: SingleBiu
 * @Date: 2023-03-04 19:21:18
 * @LastEditors: SingleBiu
 * @LastEditTime: 2023-03-04 19:52:55
 * @Description: 线程池头文件
 */
#if !defined(__POOL_H__)
#define __POOL_H__

#include<pthread.h>
#include<string.h>

//构建任务队列结点
typedef struct task_node
{
    void *(*task)(void *arg);   //函数指针
                                //一个函数就是一个任务
                                //一个函数执行完 那么任务就算完成

    void *arg;                  //指向函数的参数

    int arg_len;                //arg指向对象的长度

    struct task_node *next;     //指向下一个任务结点
} TASK;

//构建线程池的类型
typedef struct thread_pool
{
    pthread_t *p_id;            //线程id集合

    int task_len;               //任务队列长度

    int active_thread;          //活跃的线程数

    int shutdown;               //关机位
                                // 0 进程不结束
                                // 1 进程结束
                                
    TASK *head;                 //任务队列的头结点

    pthread_mutex_t mutex;      //锁 保护共享资源

    pthread_cond_t cond;       //条件变量 用于唤醒线程
} THREAD_POOL;

// 初始化一个线程池 分配一个线程池结构体
THREAD_POOL *init_pool();

// 往线程池的任务队列上添加任务
int add_task(THREAD_POOL *pool, void *(*func)(void *), void *arg, int arg_len);

// 销毁线程池
int destory_pool(THREAD_POOL *pool);

#endif // __POOL_H__

pool.c:

cpp 复制代码
/*
 * @Author: SingleBiu
 * @Date: 2023-03-04 19:21:12
 * @LastEditors: SingleBiu
 * @LastEditTime: 2023-03-05 11:15:02
 * @Description: 线程池代码
 */
#include <stdio.h>
#include <stdlib.h>
#include "../inc/pool.h"

#define MAX_THREAD 8 // 线程池最大线程数

/**
 * @description: 线程函数
 * @param {void} *arg   线程函数参数
 * @return {*}
 */
void *func(void *arg)
{
    THREAD_POOL *pool = (THREAD_POOL *)arg;

    while (1)
    {
        pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);

        pthread_mutex_lock(&pool->mutex);

        while (pool->task_len == 0 && pool->shutdown == 0) // 无任务执行 且 未关机
        {
            pthread_cond_wait(&pool->cond, &pool->mutex); // 线程睡眠
        }

        // 要么关机 要么执行任务
        if (pool->shutdown == 1)
        {
            pthread_mutex_unlock(&pool->mutex);
            pthread_exit(0);
        }

        // 执行任务
        TASK *t = pool->head->next; // 取出开头的任务
        pool->head->next = t->next; // 头结点后移
        t->next = NULL;             // 取下任务结点
        pool->task_len--;           // 任务数量减一

        pthread_mutex_unlock(&pool->mutex); // 之后无需访问共享资源

        pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);

        // 执行任务函数
        t->task(t->arg);

        free(t->arg);
        free(t); // 释放申请的空间
    }
}

/**
 * @description: 初始化线程池
 * @return {*}
 */
THREAD_POOL *init_pool()
{
    THREAD_POOL *pool = (THREAD_POOL *)malloc(sizeof(*pool));
    if (NULL == pool)
    {
        perror("malloc error\n");
        return NULL;
    }

    pool->task_len = 0; // 任务队列清空

    pool->shutdown = 0; // 0 表示不关机

    // 创建头结点保证任务队列不为空
    pool->head = malloc(sizeof(TASK));
    if (pool->head == NULL)
    {
        free(pool);
        perror("mallo error");
        return NULL;
    }

    pool->head->next = NULL; // 指向空 表示任务队列为空

    pthread_mutex_init(&pool->mutex, NULL); // 初始化锁
    pthread_cond_init(&pool->cond, NULL);   // 初始化条件变量

    pool->p_id = malloc(sizeof(pthread_t *) * MAX_THREAD); // 线程id集合

    pool->active_thread = 0; // 已创建的线程个数
    int i;                   // 线程创建次数
    int j = 0;               // 线程成功创建次数

    for (i = 0; i < MAX_THREAD; i++)
    {
        if (pthread_create(&pool->p_id[j], NULL, func, pool) != -1)
        {
            j++;
            pool->active_thread++;
            printf("success created thread[%d] pid = %ld\n", j, pool->p_id[j]);
        }
    }

    return pool;
}

/**
 * @description: 添加任务函数
 * @param {THREAD_POOL} *pool     线程池结构体指针
 * @param {void} *(*func)(void *) 函数指针
 * @param {void} *arg             函数参数
 * @param {int} arg_len           函数参数长度
 * @return {int} 0 正常 | -1 失败
 */
int add_task(THREAD_POOL *pool, void *(*func)(void *), void *arg, int arg_len)
{
    if (NULL == pool)
    {
        return -1;
    }

    TASK *new = malloc(sizeof(TASK));

    if (NULL == new)
    {
        perror("malloc error\n");
        return -1;
    }

    new->task = func;               // 添加任务函数
    new->arg = malloc(arg_len);     // 分配参数空间
    memcpy(new->arg, arg, arg_len); // 复制参数到申请的空间
    new->next = NULL;

    pthread_mutex_lock(&pool->mutex); // 保护任务队列

    TASK *task = pool->head;

    while (NULL != task->next)
    {
        task = task->next;
    }
    task->next = new; // 添加任务到队尾

    pool->task_len++; // 任务数加一

    pthread_cond_signal(&pool->cond); // 唤醒一个线程执行任务

    pthread_mutex_unlock(&pool->mutex);

    return 0;
}

/**
 * @description: 销毁线程池
 * @param {THREAD_POOL} *pool 线程池结构体指针
 * @return {int} 0 正常 | -1 失败
 */
int destory_pool(THREAD_POOL *pool)
{
    pool->shutdown = 1;                  // 关机位置1
    pthread_cond_broadcast(&pool->cond); // 唤醒所有线程自杀

    int i;
    for (i = 0; i < pool->active_thread; i++)
    {
        pthread_join(pool->p_id[i],NULL);   //回收线程资源

        printf("joined thread[%d] pid = %ld\n",i,pool->p_id[i]);
    }

    free(pool->p_id);
    free(pool->head);
    free(pool);

    return 0;
}

main.c:

cpp 复制代码
/*
 * @Author: SingleBiu
 * @Date: 2023-03-04 19:04:13
 * @LastEditors: SingleBiu
 * @LastEditTime: 2023-03-05 11:30:15
 * @Description: 线程池应用
 */
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include "sys/time.h"
#include "../inc/pool.h"

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

int g_ticket = 1000000;

void *get_g_ticket(void *arg)
{
    int times = *(int *)arg;

    while (g_ticket > 0 && times > 0)
    {
        if (0 == pthread_mutex_trylock(&mutex))
        {
            printf("g_ticket1:%d\n", --g_ticket);
            pthread_mutex_unlock(&mutex);
            times--;
        }
        else
        {
            // printf("lock is in use 1\n");
        }
    }
}

void *get_g_ticket2(void *arg2)
{
    int times = *(int *)arg2;

    while (g_ticket > 0 && times > 0)
    {
        if (0 == pthread_mutex_trylock(&mutex))
        {
            printf("g_ticket2:%d\n", --g_ticket);
            pthread_mutex_unlock(&mutex);
            times--;
        }
        else
        {
            // printf("lock is in use 2\n");
        }
    }
}

int main(int argc, char const *argv[])
{
    THREAD_POOL *thread_pool = init_pool();

    int arg = 500000;
    int arg2 = 500000;

    struct timeval time_start, time_end;

    gettimeofday(&time_start, NULL);

    add_task(thread_pool, &get_g_ticket, &arg, sizeof(arg));

    add_task(thread_pool, &get_g_ticket2, &arg2, sizeof(arg2));

    sleep(1);

    destory_pool(thread_pool);

    gettimeofday(&time_end, NULL);

    int timeuse = 1000000 * (time_end.tv_sec - time_start.tv_sec) + time_end.tv_usec - time_start.tv_usec;

    printf("Used:%d ms\n", timeuse / 1000);

    return 0;
}

makefile:

bash 复制代码
TARGET := ../bin/main

CC := gcc

CPP := g++ -std=c++11

CSRCS :=$(wildcard *.c)

CPPSRCS :=$(wildcard *.cpp)

O_PATH = ../obj

OBJS := $(patsubst %.c, $(O_PATH)/%.o, $(CSRCS))

OBJS += $(patsubst %.cpp, $(O_PATH)/%.o, $(CPPSRCS))

INC := -I ./ -I ../inc

LIBS := -l pthread

$(TARGET):$(OBJS)
	$(CC) $^ $(LIBS) -o $@

$(O_PATH)/%.o:%.c 
	$(CC) -c $< $(INC) -o $@

$(O_PATH)%.o:%.cpp 
	$(CPP) -c $< $(INC) -o $@

clean:
	rm -rf  $(OBJS)
	rm -rf  $(TARGET)
相关推荐
正点原子18 分钟前
【正点原子STM32MP257连载】第二章 ATK-DLMP257B使用前准备 #串口软件 #MobaXterm
linux·stm32·单片机·嵌入式硬件
苏卫苏卫苏卫34 分钟前
【Vue】案例——To do list:
开发语言·前端·javascript·vue.js·笔记·list
life_time_39 分钟前
C语言-习题整理(1)
c语言·开发语言
18你磊哥1 小时前
java中使用微服务的痛点有哪些,怎么解决
java·开发语言·微服务
MobiCetus1 小时前
Linux Kernel 7
linux·运维·服务器·windows·ubuntu·centos·gnu
三天不学习1 小时前
Python快速入门指南:从零开始掌握Python编程
开发语言·python
西洼工作室1 小时前
centos时间不正确解决
linux·运维·centos
精彩漂亮ing1 小时前
CExercise_13_1排序算法_2归并排序
算法·排序算法
摆烂能手1 小时前
C++基础精讲-06
开发语言·c++
再学一丢丢1 小时前
用户管理和权限管理
linux·运维·服务器