[代码实例][C]Linux实现线程池

ThreadPool.h

#ifndef THREADPOOL_H
#define THREADPOOL_H

#include <stdbool.h>

#include <pthread.h>

struct ThreadJob
{
	void* (*CallbackFunction)(void *arg);	// 线程回调函数
	void * Arg;								// 回调函数参数
	struct ThreadJob * Next;
};

typedef struct
{
	int ThreadCount;					// 线程池中开启线程的个数
	int QueueMaxCount;					// 队列中最大ThreadJob的个数
	struct ThreadJob * JobQueueHead;	// 指向ThreadJob的头指针
	struct ThreadJob * JobQueueTail;	// 指向ThreadJob的尾指针
	pthread_t * Threads;				// 线程池中所有线程的pthread_t
	pthread_mutex_t Mutex;				// 互斥信号量
	pthread_cond_t QueueEmptyCond;		// 队列为空的条件变量
	pthread_cond_t QueueNotEmptyCond;	// 队列不为空的条件变量
	pthread_cond_t QueueNotFullCond;	// 队列不为满的条件变量
	int QueueCount;						// 队列当前的ThreadJob个数
	bool IsQueueClosed;					// 队列是否已经关闭
	bool IsPoolClosed;					// 线程池是否已经关闭
} ThreadPool;

/*
 * Function: ThreadPool_Init
 * Description: 初始化线程池。
 * Arguments:
 *	@threadCount: 线程池大小。
 *	@queueMaxCount: 线程池队列大小。
 * Return: 指向线程池的指针。
 */
ThreadPool * ThreadPool_Init(int threadCount, int queueMaxCount);

/*
 * Function: ThreadPool_AddJob
 * Description: 向线程池添加任务。
 * Arguments:
 *	@threadPool: 指向线程池的指针。
 *	@callbackFunction: 线程回调函数。
 *	@arg: 回调函数参数。
 * Return: null。
 */
void ThreadPool_AddJob(ThreadPool * threadPool, void * (*callbackFunction)(void * arg), void * arg);

/*
 * Function: ThreadPool_Destroy
 * Description: 销毁线程池。
 * Arguments:
 *	@threadPool: 指向线程池的指针。
 * Return: null。
 */
void ThreadPool_Destroy(ThreadPool * threadPool);

#endif

ThreadPool.c

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

#include <stdbool.h>

#include "ThreadPool.h"

static void * _function(void * arg)
{
	if(!arg)
	{
		fprintf(stderr, "[_function()] Argument 'arg' is invalid");
		exit(EXIT_FAILURE);
	}

	ThreadPool * threadPool = (ThreadPool *)arg;

	struct ThreadJob *threadJob = NULL;
	while (true)
	{
		pthread_mutex_lock(&(threadPool->Mutex));

		//队列为空时,就等待队列非空
		while (threadPool->QueueCount == 0 && !threadPool->IsPoolClosed)
			pthread_cond_wait(&(threadPool->QueueNotEmptyCond), &(threadPool->Mutex));
		
		//线程池关闭
		if (threadPool->IsPoolClosed)
		{
			pthread_mutex_unlock(&(threadPool->Mutex));
			pthread_exit(NULL);
		}

		threadPool->QueueCount--;
		threadJob = threadPool->JobQueueHead;
		if (threadPool->QueueCount == 0)
		{
			threadPool->JobQueueHead = NULL;
			threadPool->JobQueueTail = NULL;
		}
		else
			threadPool->JobQueueHead = threadJob->Next;

		// 若队列为空,就可以通知ThreadPool_Destroy函数,销毁线程函数
		if (threadPool->QueueCount == 0)
			pthread_cond_signal(&(threadPool->QueueEmptyCond));
		
		// 队列非满,就可以通知ThreadPool_AddJob函数,添加新任务
		if (threadPool->QueueCount == threadPool->QueueMaxCount - 1)
			pthread_cond_broadcast(&(threadPool->QueueNotFullCond));  
		
		pthread_mutex_unlock(&(threadPool->Mutex));
		
		// 线程真正要做的任务,回调函数的调用
		(*(threadJob->CallbackFunction))(threadJob->Arg);
		
		free(threadJob);
	}
}

ThreadPool * ThreadPool_Init(int threadCount, int queueMaxCount)
{
	ThreadPool * threadPool = NULL;

	threadPool = malloc(sizeof(ThreadPool));
	if (!threadPool)
	{
		perror("[ThreadPool_Init()] malloc");
		exit(EXIT_FAILURE);
	}

	threadPool->ThreadCount = threadCount;
	threadPool->QueueMaxCount = queueMaxCount;
	threadPool->QueueCount = 0;
	threadPool->JobQueueHead = NULL;
	threadPool->JobQueueTail = NULL;
		
	if (pthread_mutex_init(&(threadPool->Mutex), NULL))
	{
		perror("[ThreadPool_Init()] pthread_mutex_init");
		exit(EXIT_FAILURE);
	}
	if (pthread_cond_init(&(threadPool->QueueEmptyCond), NULL))
	{
		perror("[ThreadPool_Init()] pthread_mutex_init");
		exit(EXIT_FAILURE);
	}
	if (pthread_cond_init(&(threadPool->QueueNotEmptyCond), NULL))
	{
		perror("[ThreadPool_Init()] pthread_cond_init");
		exit(EXIT_FAILURE);
	}
	if (pthread_cond_init(&(threadPool->QueueNotFullCond), NULL))
	{
		perror("[ThreadPool_Init()] pthread_cond_init");
		exit(EXIT_FAILURE);
	}
		
	threadPool->Threads = malloc(sizeof(pthread_t) * threadCount);
	if (!threadPool->Threads)
	{
		perror("[ThreadPool_Init()] malloc");
		exit(EXIT_FAILURE);
	}

	threadPool->IsQueueClosed = false;
	threadPool->IsPoolClosed = false;
	for (int i = 0; i < threadPool->ThreadCount; ++i)
		pthread_create(&(threadPool->Threads[i]), NULL, _function, threadPool);
		
	return threadPool;
}

void ThreadPool_AddJob(ThreadPool * threadPool, void * (*callbackFunction)(void * arg), void * arg)
{
	if(!threadPool)
	{
		fprintf(stderr, "[ThreadPool_AddJob()] Argument 'threadPool' is invalid");
		exit(EXIT_FAILURE);
	}
	if(!callbackFunction)
	{
		fprintf(stderr, "[ThreadPool_AddJob()] Argument 'callbackFunction' is invalid");
		exit(EXIT_FAILURE);
	}

	pthread_mutex_lock(&(threadPool->Mutex));

	// 队列满的时候就等待
	while (threadPool->QueueCount == threadPool->QueueMaxCount
			&& !(threadPool->IsQueueClosed || threadPool->IsPoolClosed))
		pthread_cond_wait(&(threadPool->QueueNotFullCond), &(threadPool->Mutex));
	
	// 队列关闭或者线程池关闭就退出
	if (threadPool->IsQueueClosed || threadPool->IsPoolClosed)
	{
		fprintf(stderr, "[ThreadPool_AddJob()] ThreadPool or Queue has been closed");
		exit(EXIT_FAILURE);
	}

	struct ThreadJob * threadJob = malloc(sizeof(struct ThreadJob));
	if (!threadJob)
	{
		perror("[ThreadPool_AddJob()] malloc");
		exit(EXIT_FAILURE);
	}

	threadJob->CallbackFunction = callbackFunction;    
	threadJob->Arg = arg;
	threadJob->Next = NULL;
	
	if (threadPool->JobQueueHead == NULL)   
	{
		threadPool->JobQueueHead = threadJob;
		threadPool->JobQueueTail = threadJob;

		// 队列空的时候,有任务来时就通知线程池中的线程:队列非空
		pthread_cond_broadcast(&(threadPool->QueueNotEmptyCond));
	}
	else
	{
		threadPool->JobQueueTail->Next = threadJob;
		threadPool->JobQueueTail = threadJob;    
	}

	threadPool->QueueCount++;

	pthread_mutex_unlock(&(threadPool->Mutex));
}

void ThreadPool_Destroy(ThreadPool * threadPool)
{
	if(!threadPool)
	{
		fprintf(stderr, "[ThreadPool_AddJob()] Argument 'threadPool' is invalid");
		exit(EXIT_FAILURE);
	}

	pthread_mutex_lock(&(threadPool->Mutex));

	// 若线程池或队列已经关闭,则说明已发生内部错误
	if (threadPool->IsQueueClosed || threadPool->IsPoolClosed)
	{
		fprintf(stderr, "[ThreadPool_Destroy()] ThreadPool or Queue has been closed");
		exit(EXIT_FAILURE);
	}
	
	// 设置队列关闭
	threadPool->IsQueueClosed = true;
	// 等待队列为空
	while (threadPool->QueueCount != 0)
		pthread_cond_wait(&(threadPool->QueueEmptyCond), &(threadPool->Mutex));
	
	// 设置线程池关闭
	threadPool->IsPoolClosed = true;

	pthread_mutex_unlock(&(threadPool->Mutex));

	// 唤醒线程池中正在阻塞的线程
	pthread_cond_broadcast(&(threadPool->QueueNotEmptyCond));
	//唤醒添加任务的ThreadPool_AddJob函数
	pthread_cond_broadcast(&(threadPool->QueueNotFullCond));
	
	// 等待线程池的所有线程执行完毕
	for (int i = 0; i < threadPool->ThreadCount; ++i)
		pthread_join(threadPool->Threads[i], NULL);
	
	/* 清理相关资源 */
	pthread_mutex_destroy(&(threadPool->Mutex));
	pthread_cond_destroy(&(threadPool->QueueEmptyCond));
	pthread_cond_destroy(&(threadPool->QueueNotEmptyCond));
	pthread_cond_destroy(&(threadPool->QueueNotFullCond));
	
	free(threadPool->Threads);

	struct ThreadJob * p = NULL;
	while (threadPool->JobQueueHead != NULL)
	{
		p = threadPool->JobQueueHead;
		threadPool->JobQueueHead = p->Next;
		free(p);
	}

	free(threadPool);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值