高并发线程池(c语言)

        高并发线程池分为三个文件

        main.c

        ThreadPool.h

        ThreadPool.c

        先来看看THreadPool.h和THreadPool.c

        

#pragma once
typedef struct ThreadPool ThreadPool;//使用ThreadPool代替struct 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* work(void* arg);
void* manager(void* arg);
void threadExit(ThreadPool* pool);
#include"threadpool.h"
#include<pthread.h>
#include<malloc.h>
#include <unistd.h>

const int NUMBER = 2;
typedef struct Task//任务结构体
{
	void (*function)(void* arg);//函数指针指向函数
	void* arg;
}Task;
//线程池结构体
struct ThreadPool
{
	//任务队列
	Task* taskQ;
	int queueCapacity;		//容量
	int queueSize;			//当前任务个数
	int queueRear;			//队尾->放数据
	int queueFront;			//队头 -》取数据
	
	pthread_t manangerID;		//管理者的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;		//任务队列是不是满了,专门用来wait与唤醒的
	pthread_cond_t notEmpty;	//任务队列是不是空了,同上
	
	int shutdown;				//判断线程池是否工作,是不是销毁线程池,销毁为1,不销毁则为0
};

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->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 = 0;
		pool->liveNum = min;    // 和最小个数相等
		pool->exitNum = 0;

		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;
		}

		// 任务队列
		pool->taskQ = (Task*)malloc(sizeof(Task) * queueSize);
		pool->queueCapacity = queueSize;
		pool->queueSize = 0;
		pool->queueFront = 0;
		pool->queueRear = 0;

		pool->shutdown = 0;

		// 创建线程
		pthread_create(&pool->manangerID, NULL, manager, pool);
		for (int i = 0; i < min; ++i)
		{
			pthread_create(&pool->threadIDs[i], NULL, work, pool);
		}
		return pool;
	} while (0);

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

	return NULL;
}

void* work(void* arg)//工作
{
	ThreadPool* pool = (ThreadPool*)arg;//拿到线程池
	while (1)
	{
		pthread_mutex_lock(&pool->mutexPool);//加锁
		//当前任务队列是否为空、
		while (pool->queueSize == 0 && !pool->shutdown)//size不为0并且未销毁,写while的原因是因为防止一个线程wait其他线程进入
		{
			//阻塞工作线程
			pthread_cond_wait(&pool->notEmpty, &pool->mutexPool);

			//判断是不是要销毁线程zisha
			if (pool->exitNum > 0)
			{
				pool->exitNum--;
				if (pool->liveNum > pool->minNum)
				{
				pool->liveNum--;
				pthread_mutex_unlock(&pool->mutexPool);
				threadExit(pool);

				}
			}
		}
		//判断线程池是否被关闭了
		if (pool->shutdown == 1)
		{
			pthread_mutex_unlock(&pool->mutexPool);//解锁
			threadExit(pool);
		}
		Task task;
		task.function = pool->taskQ[pool->queueFront].function;//获取头任务线程的func
		task.arg = pool->taskQ[pool->queueFront].arg;
		//循环队列到末尾再加一然后取余,移动头结点
		pool->queueFront = (pool->queueFront + 1)%pool->queueCapacity;//第一个节点为(0+1)%4移动到第二个……第四个节点为(3+1)%4移动到第一个
		pool->queueSize--;//任务队列减一
		pthread_cond_signal(&pool->notFull);
		pthread_mutex_unlock(&pool->mutexPool);//解锁
		printf("thread %ld start working\n", pthread_self());
		//busyNum改变
		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->mutexPool);
		pool->busyNum--;
		pthread_mutex_unlock(&pool->mutexPool);
		
	}
	return NULL;
}

void* manager(void* arg)
{
	ThreadPool* pool = (ThreadPool*)arg;
	while (pool->shutdown != 1)
	{
		//每隔3秒检测一次
		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, work, 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);
	}
}

void threadPoolAdd(ThreadPool* pool, void(*func)(void*), void* arg)
{
	pthread_mutex_lock(&pool->mutexPool);
	while (pool->queueSize == pool->queueCapacity && !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->queueCapacity;//回到队头
	pool->queueSize++;
	pthread_cond_signal(&pool->notEmpty);//唤醒

	pthread_mutex_unlock(&pool->mutexPool);
}

int threadPoolDestroy(ThreadPool* pool)
{
	if (pool == NULL)
	{
		return -1;
	}

	// 关闭线程池
	pool->shutdown = 1;
	// 阻塞回收管理者线程
	pthread_join(pool->manangerID, 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;
}

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.c

#include"threadpool.h"
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<stdlib.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 < 100; ++i)
    {
        int* num = (int*)malloc(sizeof(int));
        *num = i + 100;
        threadPoolAdd(pool, taskFunc, num);
    }

    sleep(30);

    threadPoolDestroy(pool);
    return 0;
}

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值