线程池C代码实现(linux环境测试)

线程池C代码实现


文章目录

  • 线程池C代码实现
  • 前言
  • 一、代码实现框架
  • 二、代码
    • 1.对象定义
    • 2.队列入队和出队
    • 3.内部处理接口
    • 4.对外接口
    • 4.app测试代码
    • 5.线程池头文件
  • 总结


前言

线程池是多个线程组成的线程队列和多个任务组成的任务队列总体管理的池子,对于一些需要一个时刻创建很多线程的场合,由于对CPU造成很大的负担,有可能是实现不了的,所以线程池起到了一个缓冲的作用,使用队列的思想进行排队处理任务。


一、代码实现框架

代码框架主要如下,由线程池提供三个函数接口,分别为创建线程池,初始化线程池和注册任务(这三个接口其实还不完整,应该还需要销毁等接口,本文只是记录线程池的大概实现方法和思想)
线程池C代码实现(linux环境测试)_第1张图片

二、代码

1.对象定义

主要分为三大类

  1. 线程队列(线程对象节点定义和线程队列定义)
  2. 任务队列(任务对象节点定义和任务队列定义)
  3. 线程池管理
/**@file
 * @note CSDN Li Haoqin. All rights reserved
 * @brief 线程池源文件
 *
 *@author lihaoqin
 *@date 2020/10/10
 *
 *@version
 *  data        |version  |author               |message
 *  :-----      |:-----   |:-----               |:----
 *  2020/10/10  |V1.0.0   |lihaoqin             |创建代码文档
 *@warning
 */

#include 
#include 
#include 
#include 
#include "thread_pool.h"

#define MAX_THREAD_CNT (100u)
#define LOG printf

//线程对象节点定义
typedef struct THREADNODE
{
     
	pthread_t thread;
	int idx;
	int is_terminate;
	struct THREADNODE *next;
	struct THREADPOOL *thread_pool;
} THREADNODE, *ThreadQueuePtr;

//线程队列定义
typedef struct
{
     
	ThreadQueuePtr front, rear;
} LinkThreadQueue;

//任务对象节点定义
typedef struct JOBNODE
{
     
	JOB_CB_FUN job_cb_fun;
	int param;
	void *arg;
	struct JOBNODE *next;
} JOBNODE, *JobQueuePtr;

//任务队列定义
typedef struct
{
     
	JobQueuePtr front, rear;
} LinkJobQueue;

//线程池管理
typedef struct THREADPOOL
{
     
	int is_init;
	int thread_cnt;
	pthread_mutex_t mu;
	pthread_cond_t cond;
	LinkThreadQueue thread_queue;
	LinkJobQueue job_queue;
} THREADPOOL;

2.队列入队和出队

主要分为两大类

  1. 线程队列入队和出队
  2. 任务队列入队和出队
static int thread_enqueue(LinkThreadQueue *link, THREADNODE *node)
{
     
	if (NULL == link || NULL == node)
	{
     
		return -1;
	}
	if (NULL == link->rear)
	{
     
		return -2;
	}
	
	node->next = NULL;
	link->rear->next = node;
	link->rear = node;
	
	return 0;
}


static int thread_dequeue(LinkThreadQueue *link, THREADNODE **thread_node)
{
     
	THREADNODE *node = NULL;
	
	if (NULL == link)
	{
     
		return -1;
	}
	if (NULL == link->front || NULL == link->rear)
	{
     
		return -2;
	}
	if (link->front == link->rear)
	{
     
		return -3;
	}
	
	node = link->front->next;
	link->front->next = node->next;
	
	if (node == link->rear)
	{
     
		link->rear = link->front;
	}
	
	*(THREADNODE **)thread_node = node;
	
	return 0;
}

static int job_enqueue(LinkJobQueue *link, JOBNODE *node)
{
     
	if (NULL == link || NULL == node)
	{
     
		return -1;
	}
	if (NULL == link->rear)
	{
     
		return -2;
	}
	
	node->next = NULL;
	link->rear->next = node;
	link->rear = node;
	
	return 0;
}


static int job_dequeue(LinkJobQueue *link, JOBNODE **job_node)
{
     
	JOBNODE *node = NULL;
	
	if (NULL == link)
	{
     
		return -1;
	}
	if (NULL == link->front || NULL == link->rear)
	{
     
		return -2;
	}
	if (link->front == link->rear)
	{
     
		return -3;
	}
	
	node = link->front->next;
	link->front->next = node->next;
	
	if (node == link->rear)
	{
     
		link->rear = link->front;
	}
	
	*(JOBNODE **)job_node = node;
	
	return 0;
}

3.内部处理接口

(可以理解为管理部分)

static void *thread_process(void *arg)
{
     
	THREADNODE *thread_node = (THREADNODE *)arg;
	JOBNODE *job_node = NULL;
	
	while (1)
	{
     
		pthread_mutex_lock(&thread_node->thread_pool->mu);
		
		while (0 != job_dequeue(&thread_node->thread_pool->job_queue, &job_node))
		{
     
			if (1 == thread_node->is_terminate)
			{
     
				break;
			}
			pthread_cond_wait(&thread_node->thread_pool->cond, &thread_node->thread_pool->mu);
		}
		
		pthread_mutex_unlock(&thread_node->thread_pool->mu);
		if (1 == thread_node->is_terminate)
		{
     
			break;
		}
		
		if (NULL == job_node)
		{
     
			continue;
		}
		job_node->job_cb_fun(job_node->param, job_node->arg);
		free(job_node);
	}
	
	free(thread_node);
	pthread_exit(NULL);
}

4.对外接口

  1. 创建线程池:传入需要创建多少个线程作为线程池处理线程
int thread_pool_create(void **handle, int thread_cnt)
{
     
   THREADPOOL *thread_pool = NULL;
   
   if (NULL == handle)
   {
     
   	LOG("%s[%d] param is null\n", __FUNCTION__, __LINE__);
   	return -1;
   }
   if ((0 == thread_cnt) || (MAX_THREAD_CNT < thread_cnt))
   {
     
   	LOG("%s[%d] thread cnt error\n", __FUNCTION__, __LINE__);
   	return -2;
   }
   
   thread_pool = (THREADPOOL *)malloc(sizeof(THREADPOOL));
   memset(thread_pool, 0, sizeof(THREADPOOL));
   thread_pool->thread_cnt = thread_cnt;
   
   *(THREADPOOL **)handle = thread_pool;
   
   return 0;
}
  1. 线程池初始化接口:调用此接口使得线程池开始工作
int thread_pool_init(void *handle)
{
     
	THREADNODE *thread_node = NULL;
	JOBNODE *job_node = NULL;
	THREADPOOL *thread_pool = (THREADPOOL *)handle;
	int idx = 0;
	int ret = 0;
	
	if (NULL == thread_pool)
	{
     
		LOG("%s[%d] param is null\n", __FUNCTION__, __LINE__);
		return -1;
	}
	if (1 == thread_pool->is_init)
	{
     
		LOG("%s[%d] thread pool is already init\n", __FUNCTION__, __LINE__);
		return -2;
	}
	
	pthread_mutex_t mutex_tmp = PTHREAD_MUTEX_INITIALIZER;
	memcpy(&thread_pool->mu, &mutex_tmp, sizeof(thread_pool->mu));
	
	pthread_cond_t cond_tmp = PTHREAD_COND_INITIALIZER;
	memcpy(&thread_pool->cond, &cond_tmp, sizeof(thread_pool->cond));
	
	thread_node = (THREADNODE *)malloc(sizeof(THREADNODE));
	if (NULL == thread_node)
	{
     
		LOG("%s[%d] thread node malloc failed\n", __FUNCTION__, __LINE__);
		return -3;
	}
	job_node = (JOBNODE *)malloc(sizeof(JOBNODE));
	if (NULL == job_node)
	{
     
		LOG("%s[%d] job node malloc failed\n", __FUNCTION__, __LINE__);
		return -4;
	}
	thread_pool->thread_queue.front = thread_node;
	thread_pool->thread_queue.rear = thread_node;
	
	thread_pool->job_queue.front = job_node;
	thread_pool->job_queue.rear = job_node;
	
	for (idx = 0; idx < thread_pool->thread_cnt; idx++)
	{
     
		thread_node = (THREADNODE *)malloc(sizeof(THREADNODE));
		if (NULL == thread_node)
		{
     
			LOG("%s[%d] thread %d node malloc failed\n", __FUNCTION__, __LINE__, idx);
			return -5;
		}
		memset(thread_node, 0, sizeof(thread_node));
		
		thread_node->idx = idx;
		thread_node->thread_pool = thread_pool;
		ret = pthread_create(&thread_node->thread, NULL, thread_process, thread_node);
		if (0 != ret)
		{
     
			LOG("%s[%d] thread  %d create failed\n", __FUNCTION__, __LINE__, idx);
			return -6;
		}
		
		ret = thread_enqueue(&thread_pool->thread_queue, thread_node);
		if (0 != ret )
		{
     
			LOG("%s[%d] thread_enqueue %d failed\n", __FUNCTION__, __LINE__, idx);
			return -7;
		}
	}
	
	thread_pool->is_init = 1;
	
	return 0;
}
  1. 任务注册接口(注册任务,传入回调函数和参数)
int register_job(void *handle, JOB_CB_FUN cb, int param, void *arg)
{
     
	THREADPOOL *thread_pool = (THREADPOOL *)handle;
	JOBNODE *job_node = NULL;
	int ret = 0;
	
	if (NULL == thread_pool)
	{
     
		LOG("%s[%d] param is null\n", __FUNCTION__, __LINE__);
		return -1;
	}
	if (0 == thread_pool->is_init)
	{
     
		LOG("%s[%d] thread pool is already init\n", __FUNCTION__, __LINE__);
		return -2;
	}
	
	job_node = (JOBNODE *)malloc(sizeof(JOBNODE));
	if (NULL == job_node)
	{
     
		LOG("%s[%d] malloc job node failed\n", __FUNCTION__, __LINE__);
		return -3;
	}
	
	job_node->job_cb_fun = cb;
	job_node->param = param;
	job_node->arg = arg;
	
	pthread_mutex_lock(&thread_pool->mu);
	
	ret = job_enqueue(&thread_pool->job_queue, job_node);
	if (NULL == job_node)
	{
     
		LOG("%s[%d] job_enqueue failed\n", __FUNCTION__, __LINE__);
		pthread_mutex_unlock(&thread_pool->mu);
		return -4;
	}
	
	pthread_cond_signal(&thread_pool->cond);
	pthread_mutex_unlock(&thread_pool->mu);
	
	return 0;
}

4.app测试代码

/**@file
 * @note CSDN Li Haoqin. All rights reserved
 * @brief app线程池测试文件
 *
 *@author lihaoqin
 *@date 2020/10/10
 *
 *@version
 *  data        |version  |author               |message
 *  :-----      |:-----   |:-----               |:----
 *  2020/10/10  |V1.0.0   |lihaoqin             |创建代码文档
 *@warning
 */
 
#include 
#include "thread_pool.h"


#define LOG printf

void job_cb_fun(int param, void *arg)
{
     
	LOG("%d --------------\n", param);
}

int main(int argc, char *argv[])
{
     
	void *handle;
	int ret = 0;
	int i = 0;
	
	ret = thread_pool_create(&handle, atoi(argv[1]));
	if (0 != ret)
	{
     
		LOG("%s[%d] thread_pool_create failed with ret %d\n", __FUNCTION__, __LINE__, ret);
		return -1;
	}
	
	ret = thread_pool_init(handle);
	if (0 != ret)
	{
     
		LOG("%s[%d] thread_pool_init failed with ret %d\n", __FUNCTION__, __LINE__, ret);
		return -2;
	}
	
	for (i = 0; i < 100000; i++)
	{
     
		register_job(handle, job_cb_fun, i, NULL);
	}
	getchar();
	
	return 0;
}

5.线程池头文件

主要是声明外部调用接口。

/**@file
 * @note CSDN Li Haoqin. All rights reserved
 * @brief 线程池头文件
 *
 *@author lihaoqin
 *@date 2020/10/10
 *
 *@version
 *  data        |version  |author               |message
 *  :-----      |:-----   |:-----               |:----
 *  2020/10/10  |V1.0.0   |lihaoqin             |创建代码文档
 *@warning
 */

#ifndef __THREAD_POOL_H_
#define __THREAD_POOL_H_

#ifdef __cplusplus
extern "C" {
     
#endif

typedef void (*JOB_CB_FUN)(int param, void *arg);

int thread_pool_create(void **handle, int thread_cnt);
int thread_pool_init(void *handle);
int register_job(void *handle, JOB_CB_FUN cb, int param, void *arg);

#ifdef __cplusplus
}
#endif

#endif

总结

本文章主要是通过代码编写简单实现线程池,代码部分还有很多地方设计不完善,但是可以大概了解线程池实现方法和应用。

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