Linux系统编程之【线程池】

线程池

线程池(thread pool)
线程池时一种多线程处理形式,处理过程 将任务添加到任务队列上,
然后在创建线程后自动启动这些任务

注意:
		1. 任务队列刚开始是没有任务,是一个具有头结点的空链队列
		2. 使用互斥锁来保护这个任务链表
		3. 是使用条件变量来代表任务队列上任务个数的变化 
		4. 通过一个公共开关--shutdown 来控制线程的退出,进而销毁整个线程池
		5. 活动线程执行完任务函数之后不会退出,继续向生产者索要任务,继续执行,没有任务
				进行休眠
线程池的接口函数:
		1.初始化线程池
			bool init_pool(thread_pool*pool,int thread_num);
			
		2.添加任务
			bool add_task(thread_pool*pool,void*(*do_task)(void*),void*arg);
		
		3.销毁线程池
			bool destroy_pool(thread_pool*pool);//看具体空间段
		
		4. 往线程池中添加活动线程
		....
		
		
	NAME
       pthread_cleanup_push, pthread_cleanup_pop - push and pop thread cancel‐
       lation clean-up handlers

SYNOPSIS
       #include <pthread.h>
		这两个函数专门用于防止线程被取消后死锁的
		//在线程死亡的时候做清理工作
       void pthread_cleanup_push(void (*routine)(void *),
                                 void *arg);//清理函数入栈
       void pthread_cleanup_pop(int execute);//出栈

       Compile and link with -pthread.

	注意:
		这是匹配使用
#ifndef __THREAD_POOL__
#define __THREAD_POOL__
#include <pthread.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
struct task_node
{
    void*(*do_task)(void*);
    void*arg;
    struct task_node*next;
};
struct Head//队列头节点
{
    struct task_node* first;
    struct task_node* last;
    int num;
};
//声明线程池类型
typedef struct thread_pool
{
    pthread_mutex_t mutex;//互斥锁
    pthread_cond_t cond;//条件变量

    bool shutdown;//开关  是否关闭

    int task_max;//最大任务数

    struct Head*h;//任务队列头节点指针

    int threads_max;//线程最大数
    int threads_num;//活动线程数

    pthread_t *tid;//指针,指向线程ID数组空间

    //。。。

}thread_pool;

extern bool init_pool(thread_pool*pool,int thread_num);

extern bool add_task(thread_pool*pool,void*(*do_task)(void*),void*arg);

extern bool destroy_pool(thread_pool*pool);

#endif
#include "thread_pool.h"
#define TASK_MAX 1024
#define THREADS_MAX 20

void handle(void*arg)
{
    thread_pool* pool = (thread_pool*)arg;
    pthread_mutex_unlock(&pool->mutex);
}
//线程函数
void*thread_running(void* arg)
{
    thread_pool* pool = (thread_pool*)arg;
    struct task_node*p = NULL;//执行要执行的任务节点
    while(1)
    {
        //上锁之前注册一个清理函数,避免被取消死锁
        pthread_cleanup_push(handle,pool);
        //1.上锁访问任务队列
        pthread_mutex_lock(&pool->mutex);


        //2. 访问任务队列
        // 无任务且线程池未关闭  wait
        while(pool->h->num == 0 && !pool->shutdown)//被唤醒之后检测条件是否依然满足
        {
            pthread_cond_wait(&pool->cond, &pool->mutex);
            //唤醒:
            //1. 有任务
            //2. 线程池要关闭的时候
        }

        // 无任务且线程池关闭  线程死亡
        if(pool->h->num == 0 && pool->shutdown)
        {
            //先解锁在退出
            pthread_mutex_unlock(&pool->mutex);
            pthread_exit(NULL);
        }

        // 有任务开始在任务队列上拿去任务节点
        p = pool->h->first;
        pool->h->first = p->next;// pool->h->first = pool->h->first->next;
        pool->h->num--;


        //拿去任务之后解锁
        pthread_mutex_unlock(&pool->mutex);

        //出栈刚刚注册用不到的清理函数
        pthread_cleanup_pop(0);

        //3. 执行任务
        //执行任务之前设置不可被取消
        pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
        //执行任务
        p->do_task(p->arg);// 使用函数指针调用任务函数
        //执行任务之后设置可被取消
        pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
       
        free(p);
        p = NULL;
    }
}
/*
    init_pool:初始化一个线程池
    @pool: 指向要初始的线程池
    @thread_num:线程池中的活动线程数

    返回值:
        成功 返回true
        失败 返回false
*/
bool init_pool(thread_pool*pool,int thread_num)
{
    pthread_mutex_init(&pool->mutex, NULL);//初始互斥锁
    pthread_cond_init(&pool->cond, NULL);//初始条件变量

    pool->shutdown = false;//非 关闭状态

    pool->task_max = TASK_MAX;

    pool->h = malloc(sizeof(struct Head));//任务队列头节点指针
    if(pool->h == NULL)
        return false;
    pool->h->first = pool->h->last = NULL;
    pool->h->num = 0;//任务队列的节点数 0 

    pool->threads_max = THREADS_MAX;//线程最大数
    if(thread_num > THREADS_MAX)
        pool->threads_num = THREADS_MAX;//活动线程数
    else
        pool->threads_num = thread_num;

    pool->tid = malloc(THREADS_MAX*sizeof(pthread_t));//指针,指向线程ID数组空间
    if(pool->tid == NULL)
    {
        free(pool->h);
        return false;
    }
       
    
    for(int i = 0; i < pool->threads_num; i++)
    {
        int re = pthread_create(&pool->tid[i], NULL, thread_running, pool);
        if(re == -1)
        {
            perror("pthread_create :");
            return false;
        }
    }

    return true;
}

/*
    add_task:往线程池中添加任务
    @pool :执行要操作的线程池
    @do_task:函数指针
                执行要执行的任务函数
    @arg: 任务函数 的参数


    返回值:
        成功 真
        失败  假
*/
bool add_task(thread_pool*pool,void*(*do_task)(void*),void*arg)
{
    if(pool == NULL)
        return false;
    //创建新节点
    struct task_node*pnew = malloc(sizeof(*pnew));
    if(pnew == NULL)
        return false;
    pnew->do_task = do_task;
    pnew->arg = arg;
    pnew->next = NULL;

    //增加到任务队列上
    pthread_mutex_lock(&pool->mutex);
    //任务队列满队
    if(pool->h->num == pool->task_max)
    {
        free(pnew);
        pthread_mutex_unlock(&pool->mutex);
        return false;
    }

    if(pool->h->num == 0)//空队列
    {
        pool->h->first = pool->h->last = pnew;
    }
    else
    {
        pool->h->last->next = pnew;
        pool->h->last = pnew;
    }
    pool->h->num++;

    pthread_mutex_unlock(&pool->mutex);
    pthread_cond_signal(&pool->cond);
    return true;

}

/*

*/
bool destroy_pool(thread_pool*pool)
{
    pool->shutdown = true;//开关  是否关闭
    //唤醒所有的睡眠线程
    pthread_cond_broadcast(&pool->cond);
    //等待所有活动线程死亡
    for(int i = 0; i < pool->threads_num; i++)
    {
        pthread_join(pool->tid[i], NULL);
    }

    free(pool->h);
    free(pool->tid);//指针,指向线程ID数组空间

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

    //free(pool);
    return true;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值