C语言Linux线程池代码

C语言实现简易Linux线程池代码,应对TCP高并发

  • 一、创建线程池时要解决的问题
    • 1.向线程传递任务信息
    • 2.任务在子线程之间的分配
    • 3.线程的有序退出
  • 二、 线程池的创建步骤
  • 二、线程池的退出
  • 三、改进方向

一、创建线程池时要解决的问题

线程池是为了处理一系列重复且高并发的任务而定义出来的对任务进行分配的数据类型。
线程池的核心是对任务进行分配,所以其必须包括任务以及工作线程以及分配的逻辑函数

  • 应对高并发任务时,
  • 1.主线程需要提前注册好一定数量的线程,并让其处于休眠状态。
  • 2.当有新的任务到来时,唤醒一个线程,分配给他这个任务,由线程执行此任务
  • 3.主线程继续等待下一个任务。
  • 4.子线程完成任务后,再次进入休眠状态,等待下一个任务。
  • 需要解决的问题:
    1. 如何向线程传递任务信息
    2. 任务如何在线程之间分配,线程之间的竞争机制
    3. 如何执行线程的有序退出

1.向线程传递任务信息

由于线程函数可以接收一个void*类型的参数,因此可以将任务信息打包成一个结构体,传递给子线程。

//1.以TCP连接下载为例,需要向子进程传递需要连接的客户端连接,以及其他任务信息,//可以使用此结构作为统一接口,后面如有修改直接增加即可

typedef struct task{
   
	int clientFD;	//客户端TCP套接字文件描述符
	int cmd;	//后续使用
	char name[256];//后续使用
}task_t,*ptask_t;

//2.当任务数量大于子线程数列时,需要考虑使用一个数据结构,将任务信息存储起来,
//由于任务先进先出的性质,可以使用队列实现

//2.1队列节点定义
typedef struct node{
   
	task_t data;   //任务信息
	struct node* pNext;//下一个node节点指针
}node_t,*pnode_t;

//2.2队列定义
typedef struct workQueue{
   
	pnode_t pfront;
	pnode_t prear;
	int num;		//队列中节点数量
}workQueue_t,*pworkQueue_t;

2.任务在子线程之间的分配

  • 由于线程之间共享一块虚拟内存区域,因此需要考虑资源的竞争。
    所有线程均从任务队列中拿任务,因此,要保证单个线程拿任务信息时不受其他线程的影响,因此需要在传入参数中加入pthread_mutex_t变量
  • 当队列中无任务时,线程需要阻塞等待,因此考虑加入一个pthread_cond_t变量
  • 因为对于所有子进程来说,以上两个变量都应该相同,子线程的传入参数时任务队列的指针,所以,修改上面的任务队列结构体
//任务队列结构体完整版
typedef struct workQueue{
   
	pnode_t pfront;
	pnode_t prear;
	int num;		//队列中节点数量
	int exitFlag;  //用于接收线程退出信号
	pthread_mutex_t mutex;//线程锁
	pthread_cond_t cond;	//线程条件变量
	pthread_cond_t maincond; //通知主线程的条件变量
}workQueue_t,*pworkQueue_t;
//1.任务队列的初始化
void initWQ(pworkQueue_t pqueue){
   
	memset(pqueue,0,sizeof(workQueue_t);
	pqueue->pfront = NULL;
	pqueue->prear = NULL;
	pqueue->num = 0;
	pqueue->exitFlag = 0;
	pthread_mutex_init(&queue->mutex,NULL);
	pthread_cond_init(&queue->cond,NULL);
	pthread_cond_init(&queue->maincond,NULL);
}

//2.队列中添加元素
int push(pworkQueue_t pqueue,pnode_t pnode){
   
		pnode->pNext = NULL;
		if(pqueue->pfront == NULL){
   
			pqueue->pfront = pnode;
			pqueue->prear = pnode;
		}else{
   
			pqueue->prear->pNext = pnode;
			pqueue->prear  = pnode;
		}
		pqueue->num ++;
		return 0;
}

//3.获取队首元素、需要传入非空指针的pnode
int pop(pworkQueue_t pqueue,pnode_t pnode){
   
		if(NULL == pqueue |

你可能感兴趣的:(Linux,linux,多线程,队列)