linux下C语言实现简单线程池

实现一个简单的线程池


我们知道同一进程中的多条线程将共享该进程中的全部系统资源,频繁的创建和结束线程会占用大量的系统资源,而线程池可以避免这种情况。
简单的来说,线程池就是多个线程的集合。这些线程在执行完当前任务后不会立即结束,而是执行下一个任务。若没有任务可执行,它们就会阻塞并等待下一个任务。线程池只在销毁时会结束所有线程。这样以来就避免了频繁创建和结束线程的情况,下面讲讲如何实现一个简单的线程池。
作者的线程池主要是由多个常驻线程和任务队列组成的。任务队列由链表来实现,里面的每个任务中都有相应的处理函数和内容。常驻线程在无任务时阻塞,有任务时唤醒并从任务队列中读取任务并执行。最后线程池在销毁时结束所有线程。

需要注意的时每次读取和写入任务时注意对数据的保护

下面贴出代码

#include<stdio.h>
#include <errno.h>
#include<pthread.h>
#include<stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
void my_error(const char *error_string, int line);
void add_func(void *(*func)(void *arg),void *arg);
void *mainfun(void *arg);
void init_threadpool(int max);
void destroypool();
void *simplework(void *arg);


void my_error(const char *error_string, int line) //错误处理函数
{
    fprintf(stderr, "line:%d",line);
    perror(error_string);
    exit(1);
}
struct work_list{  //定义任务队列,链表实现
    void *(*func)(void *arg);//处理函数
    void *arg;//处理函数的参数
    struct work_list *next;//指向下一个任务的指针
};
struct pthread_pool{//定义线程池
    pthread_mutex_t mutex;
    pthread_cond_t cond;
    int max_threads;
    int work_num;//剩余任务数
    int isdestroy;//是否销毁线程池
    pthread_t* thread;
    struct work_list *list_head;//指向任务队列的头结点
};
struct pthread_pool* pool;
void add_func(void *(*func)(void *arg),void *arg)   //向任务队列中添加任务
{
    struct work_list *a;
    a=(struct work_list *)malloc(sizeof(struct work_list));
    a->next=NULL;
    a->func=func;
    a->arg=arg; //使用尾插法将任务插入任务队列
    if (pool->list_head==NULL)
    {
        pool->list_head=a;
    }
    else {
        struct work_list *p;
        p=pool->list_head;
        while(p->next!=NULL)
        {
            p=p->next;
        }
        p->next=a;
    }
    pool->work_num++;
    pthread_mutex_unlock(&(pool->mutex));
    pthread_cond_signal(&(pool->cond)); //唤醒等待的线程
}
void *mainfun(void *arg) //线程
{
    while(1)
    {
        pthread_mutex_lock(&(pool->mutex));
        while(pool->list_head==NULL&&pool->work_num==0) //若无任务则进入循环,有任务就会先执行任务
        {
            if (pool->isdestroy==1)//若需要销毁线程池
            {
                pthread_mutex_unlock(&(pool->mutex));//注意退出时当前线程一定要先解锁,不然其他线程会阻塞无法退出
                printf("pthread %d has destroyed\n",pthread_self());
                pthread_exit(NULL);
            }
            else {
                printf("%d is waiting\n",pthread_self());
                pthread_cond_wait(&(pool->cond),&(pool->mutex));
                printf("%d is awake\n",pthread_self());
            }
            
        }

        struct work_list *work=pool->list_head;
        pool->list_head=pool->list_head->next;
        pool->work_num--;
        pthread_mutex_unlock(&(pool->mutex));
        (*(work->func)) (work->arg);
        free(work);
        work=NULL;
    }
    pthread_exit(NULL);
}
void init_threadpool(int max)//初始化线程池
{
    pool=(struct pthread_pool *)malloc(sizeof(struct pthread_pool));
    if (pool == NULL)
    {
        my_error("malloc",__LINE__);
    }
    pool->max_threads=max;
    pool->work_num=0;
    pool->isdestroy=0;
    pool->list_head=NULL;
    pthread_mutex_init(&(pool->mutex),NULL);
    pthread_cond_init(&(pool->cond),NULL);
    int i=0;
    pool->thread=(pthread_t*)malloc(max*sizeof(pthread_t));
    if (pool->thread == NULL)
    {
        my_error("malloc",__LINE__);
    }
    int ret;
    for (i=0;i<max;i++)
    {
        ret=pthread_create(&(pool->thread[i]),NULL,mainfun,NULL);
        if (ret!=0)
        {
            my_error("pthread_create",__LINE__);
        }
    }
    printf("init is sucess\n");
}
void destroypool()
{
    pthread_mutex_lock(&(pool->mutex));
    pool->isdestroy=1;
    pthread_mutex_unlock(&(pool->mutex));
  pthread_cond_broadcast(&(pool->cond));
    printf("i call everyone\n");
    int i=0;
    for (i=0;i<pool->max_threads;i++)
    {
        pthread_join(pool->thread[i],NULL);
    }
    free(pool->thread);
    pthread_cond_destroy(&(pool->cond));
    pthread_mutex_destroy(&(pool->mutex));
    free(pool);
}
void *simplework(void *arg)
{
    printf("%d is working %d\n",pthread_self(),*(int*)arg);
    sleep(1);
}
int main()
{
    init_threadpool(10);
    int i=0;
    for (i=0;i<5;i++)
    {
        pthread_mutex_lock(&(pool->mutex));
        add_func(simplework,&i);
    }
    sleep(5);
    destroypool();
    printf("destory compelete\n");
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言实现一个简单线程池可以按照以下步骤进行: 1. 定义线程池结构体:创建一个结构体,包含线程池中的线程数量、任务队列、互斥锁、条件变量等必要的成员。 ```c typedef struct { pthread_t *threads; // 线程数组 int thread_count; // 线程数量 task_queue_t *task_queue; // 任务队列 pthread_mutex_t mutex; // 互斥锁 pthread_cond_t cond; // 条件变量 int shutdown; // 线程池关闭标志 } thread_pool_t; ``` 2. 定义任务队列结构体:创建一个结构体,用于存储任务队列的信息,包括任务数组、任务数量、头尾指针等成员。 ```c typedef struct { task_t **tasks; // 任务数组 int task_count; // 任务数量 int head; // 队列头指针 int tail; // 队列尾指针 } task_queue_t; ``` 3. 定义任务结构体:创建一个结构体,用于存储具体的任务信息,例如任务函数指针和参数。 ```c typedef struct { void (*function)(void *); // 任务函数指针 void *argument; // 任务参数 } task_t; ``` 4. 初始化线程池:创建线程池,并初始化线程数组、任务队列、互斥锁、条件变量等。 5. 添加任务:将任务添加到任务队列中,并通过条件变量通知线程池中的线程有新任务可执行。 6. 线程函数:线程池中的线程函数,循环从任务队列中取出任务并执行。 7. 等待线程池任务完成:可以通过条件变量等待所有任务执行完毕。 8. 销毁线程池:释放线程池中的资源,包括线程数组、任务队列、互斥锁、条件变量等。 这是一个简单线程池实现的框架,你可以根据自己的需求进行具体的功能扩展和优化。注意在并发环境中使用互斥锁和条件变量来保证线程安全。希望对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值