线程池--C语言版

目录


以下内容仅供学习,如有侵权,联系作者删除。
参考作者及网站:苏丙榅;B站up主:爱编程的大丙;
链接: C语言版本线程池

threadpool.h

#ifndef _THREADPOOL_H
#define _THREADPOOL_H

typedef struct ThreadPool ThreadPool;

// 创建线程池并初始化
ThreadPool *threadPoolCreate(int min, int max, int queueSize);

// 销毁线程池
int threadPoolDestroy(ThreadPool* pool);

// 给线程池添加任务
void threadPoolAdd(ThreadPool* pool, void(*func)(void*), void* arg);

// 获取线程池中工作的线程的个数
int threadPoolBusyNum(ThreadPool* pool);

// 获取线程池中活着的线程的个数
int threadPoolAliveNum(ThreadPool* pool);

// 工作的线程(消费者线程)任务函数
void *worker(void *);

// 管理者线程任务函数
void *manager(void *);

// 单个线程退出
void threadExit(ThreadPool *pool);

#endif  // _THREADPOOL_H

threadpool.c

#include "threadpool.h"
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

const int NUMBER = 2;

// 任务结构体
typedef struct Task
{
	void (*function)(void *arg);
	void *arg;
}Task;

// 线程池结构体
typedef struct ThreadPool
{
	// 任务队列
	Task *taskQ;  
	int queueCapcity;  // 容量
	int queueSize;     // 当前任务个数
	int queueFront;    // 队头 -> 取数据
	int queueRear;	   // 队尾 -> 放数据

	pthread_t managerID;	// 管理者线程ID
	pthread_t *threadIDs;   // 工作的线程ID

	int minNum;	// 最小线程数量
	int maxNum;	// 最大线程数量

	int busyNum;	// 忙的线程的个数
	int liveNum;	// 存活的线程的个数
	int exitNum;	// 要销毁的线程个数

	pthread_mutex_t mutexPool;	// 锁整个的线程池
	pthread_mutex_t mutexBusy;	// 锁busyNum变量
	pthread_cond_t notFull;		// 任务队列是否满
	pthread_cond_t notEmpty;	// 任务队列是否空

	int shutdown;	// 是不是要销毁线程池, 销毁为1, 不销毁为0
}ThreadPool;

// 创建线程池并初始化
ThreadPool *threadPoolCreate(int min, int max, int queueSize)
{
	ThreadPool* pool = (ThreadPool *)malloc(sizeof(ThreadPool));
	do
	{
		if (pool == NULL) { printf("malloc threadpool fail...\n"); break; }


		// 任务队列	
		pool->taskQ = (Task *)malloc(sizeof(Task) * queueSize);
		if (pool->taskQ == NULL) { printf("malloc taskQ  fail...\n"); break; }

		pool->queueCapcity = queueSize;
		pool->queueFront = pool->queueRear = 0;
		pool->queueSize = 0;

		pool->threadIDs = (pthread_t *)malloc(sizeof(pthread_t) * max);
		if (pool->threadIDs == NULL) { printf("malloc threadIDs  fail...\n"); break; }
		memset(pool->threadIDs, 0, sizeof(pthread_t) * max);

		pool->minNum = min;
		pool->maxNum = max;

		pool->busyNum = pool->exitNum = 0;
		pool->liveNum = min;

		pool->shutdown = 0;

		// 创建线程
		pthread_create(&pool->managerID, NULL, manager, (void *)pool);

		for (int i = 0; i < min; ++i)
		{
			//pthread_create(pool->threadIDs + i, NULL, worker, (void *)pool);
			pthread_create(&pool->threadIDs[i], NULL, worker, (void *)pool);
		}

		if (pthread_mutex_init(&pool->mutexPool, NULL) != 0 ||
			pthread_mutex_init(&pool->mutexBusy, NULL) != 0 ||
			pthread_cond_init(&pool->notEmpty, NULL) != 0 ||
			pthread_cond_init(&pool->notFull, NULL) != 0)
		{
			printf("mutex or condition init fail...\n");
			break;
		}

		return pool;
	} while (0);

	// 释放资源
	if (pool && pool->taskQ) free(pool->taskQ);
	if (pool && pool->threadIDs) free(pool->threadIDs);

	if (pool) free(pool);
	
	return NULL;
}

void *worker(void *arg)
{
	ThreadPool *pool = (ThreadPool *)arg;

	while (1)
	{
		pthread_mutex_lock(&pool->mutexPool);

		// 当前任务队列是否为空
		while (pool->queueSize == 0 && !pool->shutdown)
		{
			// 阻塞工作线程
			pthread_cond_wait(&pool->notEmpty, &pool->mutexPool);
			
			// 判断是不是要销毁线程
			if (pool->exitNum > 0)
			{
				pool->exitNum--;
				if (pool->liveNum > pool->minNum)
				{
					pool->liveNum--;
					pthread_mutex_unlock(&pool->mutexPool);
					threadExit (pool);
				}
			}
		}

		// 判断线程池是否被关闭了
		if (pool->shutdown)
		{
			pthread_mutex_unlock(&pool->mutexPool);
			threadExit(pool);
		}

		// 从任务队列中取出一个任务
		Task task;
		task.function = pool->taskQ[pool->queueFront].function;
		task.arg = pool->taskQ[pool->queueFront].arg;

		// 移动头结点
		pool->queueFront = (pool->queueFront + 1) % pool->queueCapcity;
		pool->queueSize--;

		pthread_cond_signal(&pool->notFull);
		pthread_mutex_unlock(&pool->mutexPool);

		printf("thread %ld start working...\n", pthread_self());
		pthread_mutex_lock(&pool->mutexBusy);
		pool->busyNum++;
		pthread_mutex_unlock(&pool->mutexBusy);

		// 函数调用
		task.function(task.arg);  // 函数指针还是不理解
		free(task.arg);
		task.arg = NULL;

		printf("thread %ld end working...\n", pthread_self());
		pthread_mutex_lock(&pool->mutexBusy);
		pool->busyNum--;
		pthread_mutex_unlock(&pool->mutexBusy);
	}
}

void *manager(void *arg)
{
	ThreadPool *pool = (ThreadPool *)arg;

	while (!pool->shutdown)
	{
		// 每隔3s检测一次
		sleep(3);

		// 取出线程池中任务的数量和当前线程的数量
		pthread_mutex_lock(&pool->mutexPool);
		int queueSize = pool->queueSize;
		int liveNum = pool->liveNum;
		pthread_mutex_unlock(&pool->mutexPool);

		// 取出忙的线程的数量
		pthread_mutex_lock(&pool->mutexBusy);
		int busyNum = pool->busyNum;
		pthread_mutex_unlock(&pool->mutexBusy);

		// 添加线程
		// 任务的个数>存活的线程个数 && 存活的线程数<最大线程数
		if (queueSize > liveNum && liveNum < pool->maxNum)
		{
			pthread_mutex_lock(&pool->mutexPool);
			int counter = 0;
			for (int i = 0; i < pool->maxNum && counter < NUMBER
				&& pool->liveNum < pool->maxNum; ++i)
			{
				if (pool->threadIDs[i] == 0)
				{
					pthread_create(&pool->threadIDs[i], NULL, worker, pool);
					counter++;
					pool->liveNum++;
				}
			}
			pthread_mutex_unlock(&pool->mutexPool);
		}

		// 销毁线程
		// 忙的线程*2 < 存活的线程数 && 存活的线程>最小线程数
		if (busyNum * 2 < liveNum && liveNum > pool->minNum)
		{
			pthread_mutex_lock(&pool->mutexPool);
			pool->exitNum = NUMBER;
			pthread_mutex_unlock(&pool->mutexPool);
			// 让工作的线程自杀
			for (int i = 0; i < NUMBER; ++i)
			{
				pthread_cond_signal(&pool->notEmpty);
			}
		}
	}
	return NULL;
}

void threadExit(ThreadPool *pool)
{
	pthread_t tid = pthread_self();
	for (int i = 0; i < pool->maxNum; ++i)
	{
		if (pool->threadIDs[i] == tid)
		{
			pool->threadIDs[i] = 0;
			printf("threadExit() called, %ld exiting...\n", tid);
			break;
		}
	}
	pthread_exit(NULL);
}

// 销毁线程池
int threadPoolDestroy(ThreadPool* pool)
{
	if (pool == NULL)  return -1;

	// 关闭线程池
	pool->shutdown = 1;

	// 阻塞回收管理者线程
	pthread_join(pool->managerID, NULL);

	// 唤醒阻塞的消费者线程
	for (int i = 0; i < pool->liveNum; ++i)
	{
		pthread_cond_signal(&pool->notEmpty);
	}

	// 释放堆内存
	if (pool->taskQ)
	{
		free(pool->taskQ);
	}
	if (pool->threadIDs)
	{
		free(pool->threadIDs);
	}

	pthread_mutex_destroy(&pool->mutexPool);
	pthread_mutex_destroy(&pool->mutexBusy);
	pthread_cond_destroy(&pool->notEmpty);
	pthread_cond_destroy(&pool->notFull);

	free(pool);
	pool = NULL;

	return 0;
}

// 给线程池添加任务
void threadPoolAdd(ThreadPool* pool, void(*func)(void*), void* arg)
{
	pthread_mutex_lock(&pool->mutexPool);
	while (pool->queueSize == pool->queueCapcity && !pool->shutdown)
	{
		// 阻塞生产者线程
		pthread_cond_wait(&pool->notFull, &pool->mutexPool);
	}
	if (pool->shutdown)
	{
		pthread_mutex_unlock(&pool->mutexPool);
		return;
	}

	// 添加任务
	pool->taskQ[pool->queueRear].function = func;
	pool->taskQ[pool->queueRear].arg = arg;
	pool->queueRear = (pool->queueRear + 1) % pool->queueCapcity;
	pool->queueSize++;

	pthread_cond_signal(&pool->notEmpty);
	pthread_mutex_unlock(&pool->mutexPool);
}

// 获取线程池中工作的线程的个数
int threadPoolBusyNum(ThreadPool* pool)
{
	pthread_mutex_lock(&pool->mutexBusy);
	int busyNum = pool->busyNum;
	pthread_mutex_unlock(&pool->mutexBusy);
	return busyNum;
}

// 获取线程池中活着的线程的个数
int threadPoolAliveNum(ThreadPool* pool)
{
	pthread_mutex_lock(&pool->mutexPool);
	int aliveNum = pool->liveNum;
	pthread_mutex_unlock(&pool->mutexPool);
	return aliveNum;
}

main函数

#include <stdio.h>
#include "threadpool.c"
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>

void taskFunc(void *arg)
{
	int *num = (int *)arg;
	printf("thread %ld is working, number = %d\n", pthread_self(), *num);
	sleep(1);
}

int main()
{
	// 创建线程池
	ThreadPool* pool = threadPoolCreate(3, 10, 100);
	for (int i = 0; i < 10; ++i)
	{
		int* num = (int*)malloc(sizeof(int));
		*num = i + 10;
		threadPoolAdd(pool, taskFunc, num);
	}

	sleep(20);

	threadPoolDestroy(pool);
	return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值