系统编程之线程池、如何设计这个任务工作链表和如何设计线程池? 、 使用 命令 grep -r “关键字“ 路径

系统编程之线程池


在进程中,创建多个线程,每当有任务执行时,直接调用已创建好的线程执行,不需要额外创建线程。

实际情况是线程的数量受限于计算机内存不能创建太多,那么就可以利用线程池设置线程数量上限

在这里插入图片描述


那么如何设计这个任务工作链表?

单项不循环链表

struct task_list{
	route *fuc;//线程执行任务函数指针,该指针指向返回值void*,参数为void*的函数
	void *arg//线程执行任务函数的参数
	struct task_list *next;	
};

结构体成员是函数怎么定义
自定义一个函数类型

typedef void *(route)(void *);
	//定义了一个route为返回值void*,参数为void*的函数

如何设计线程池?

为避免多个线程争抢同一个任务,使用互斥锁
为让线程池中等待的线程知道有任务需要他们,使用条件变量通知等待的线程

struct pthread_pool{

	pthread_mutex_t   m;//互斥锁
	pthread_cond_t    v;//条件变量
	
	struct task_list *list;//任务工作链表,
							//malloc分配内存空间后,用于保存链表头部
	pthread_t *tid;//线程数组
					//malloc分配内存空间后,再确定数组大小;
	unsigned int active_pthread;//正在运行的子线程个数
	unsigned int wait_pthread;//正在等待子线程个数
	bool shutdown;//退出线程池的标志位
};

=====================================================

使用 命令 grep -r “关键字” 路径 可以查找该目录下包含该关键字的所有文件

=====================================================

任务:使用线程池实现一个简单的计时。

在这里插入图片描述

/********************************************************************
  > File Name: pthread_pool.c
  > Author: xiening
  > Mail:  1606598696@qq.com  
  > Created Time: 2020年09月07日 星期一 22时14分24秒
 *******************************************************************/

#include "pthread_pool.h"

//记时函数
void *time_delay()
{
	int t = 0;
	while(1)
	{
		printf("sec:%d\n", t);
		sleep(1);
		t++;
	}
	pthread_exit(NULL);

}

//线程执行函数
void *func(int t)
{
	printf("pid=%#x begin\n", (int)pthread_self());
	sleep(t);
	printf("pid=%#x end\n", (int)pthread_self());

//	pthread_exit(NULL);
	return NULL;
	
}


//线程池初始化,初始化结构体内的成员
void pthread_init(struct pthread_pool *pool)
{
	pthread_mutex_init(&pool->m, NULL);
	pthread_cond_init(&pool->v, NULL);

	//创建任务链表的头节点,下一个指向空表示没有任何任务
	pool->list = malloc(sizeof(struct task_list));
	if(pool->list == NULL)
		exit(0);
	pool->list->next = NULL;

	//确定子线程最大个数
	pool->tid = malloc(sizeof(pthread_t)*pthread_MAX);
	if(pool->tid == NULL)
	{
		perror("malloc tid error");
		exit(0);
	}

	//当前没有一个线程被创建且尚未有任务
	pool->active_pthread = 0;
	pool->wait_task = 0;

	pool->shutdown = false; 

}

//解除死锁函数
void handler(void *arg)
{
	struct pthread_pool *pool = (struct pthread_pool *)arg;
	pthread_mutex_unlock(&pool->m);

}

//线程执行函数
void *pthread_f(void *arg)
{
	struct pthread_pool *pool = (struct pthread_pool *)arg;

	printf("pthread = %#x begin\n", (int)pthread_self());


	//加锁前设置注册解除死锁退出函数
	pthread_cleanup_push(handler, (void *)pool);
	while(1)
	{

		//获取锁资源
		pthread_mutex_lock(&pool->m);
		
		//检查任务链表是否为空
		//如果为空则进入等待,如果不为空则执行
		while(pool->list->next == NULL && !pool->shutdown ) 
		{
			pthread_cond_wait(&pool->v, &pool->m);
		}

		//退出标志位为真时,当还有任务仍然继续执行
		if(pool->shutdown && pool->list->next == NULL)
		{
			printf("shutdown为真,任务为空\n");
			pthread_mutex_unlock(&pool->m);
			break;
		}

		//获取被执行的任务,被将该任务从节点中删除
		struct task_list *node;
		node = pool->list->next;
		pool->list->next = node->next;
		pool->wait_task--;

		//释放锁
		pthread_mutex_unlock(&pool->m);

		//设置当前线程在执行任务函数时不可取消
		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);

		//执行函数
		node->fuc(node->arg);
		free(node);

		//执行完后可以取消
		pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);

	}

	//删除注册死锁解除函数
	pthread_cleanup_pop(0);
	
	return NULL;

}

//申请创建子线程,在线程池中增加num个子线程
void pthread_pool_add(struct pthread_pool *pool, unsigned int num)
{
	if(pool->active_pthread + num > pthread_MAX)
	{
		printf("pthread_pool is full\n");
		return;
	}

	int i = 0;
	int ret = 0;
	int pthread_num = 0;
	for(i=pool->active_pthread; i<pool->active_pthread+num; i++)
	{
		ret = pthread_create(&pool->tid[i], NULL, pthread_f, (void*)pool);
		if(ret != 0)
		{
			perror("pthread_create error");
			break;
		}
		//创建成功一个线程就加一
		pthread_num++;
	}
	pool->active_pthread += pthread_num;

}

//向任务链表中添加任务
void task_add(struct pthread_pool *pool, route *fuction, int t)
{
	if(pool->wait_task >= task_MAX)
	{
		printf("task add is full\n");
		return;
	}
	struct task_list *new = malloc(sizeof(struct task_list));
	if(new == NULL)
	{
		perror("malloc struct task_list error");
		exit(0);
	}
	new->fuc = fuction;
	new->arg = t;
	new->next = NULL;

	//把新节点加入到链表末尾
	struct task_list *p = pool->list;
	while(p->next != NULL)
	{
		p = p->next;
	}
	p->next = new;

	pool->wait_task++;

	//唤醒条件变量阻塞的线程
	pthread_cond_signal(&pool->v);




}

//退出线程池
void destory_pool(struct pthread_pool *pool)
{
	//把标志位设为ture
	pool->shutdown = true;
	
	//向所有正在等待的条件变量的线程发送
	pthread_cond_broadcast(&pool->v);

	//等待所有线程结束,自动结束
	int i = 0;
	for(i=0; i<pool->active_pthread; i++)
	{
		pthread_join(pool->tid[i], NULL);
	}


	printf("线程池全部退出\n");
	//释放申请的堆内存
	free(pool->list);
	free(pool->tid);

}


int main(int argc, char const *argv[])
{
	
	//计时线程
	pthread_t tid;
	pthread_create(&tid, NULL, time_delay, NULL);


	/*
	pthread_join(tid1, NULL);
	pthread_join(tid2, NULL);
	*/

	//线程池初始化
	struct pthread_pool pool;
	pthread_init(&pool);

	//向线程池添加2个线程
	pthread_pool_add(&pool, 2);

	sleep(5);

	//添加任务
	task_add(&pool, func, 5);
	task_add(&pool, func, 7);
	task_add(&pool, func, 10);
	task_add(&pool, func, 6);


	//自动退出线程池
	destory_pool(&pool);

	pthread_cancel(tid);

	

    return 0 ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值