Linux:线程池 / 及如何创建一个线程池

线程池

线程池:通俗一点来说,就是一个有着很多线程的池子,线程数量由线程池的最大线程容量控制。当有需要处理的任务到来时,从线程池中取出一个线程去处理这个任务。

应用场景:有大量的数据处理请求,需要执行流并行或并发处理

若是每次有一个数据请求的到来需要去创建线程去处理,处理完销毁则会产生风险以及一些不必要的消耗

  1. 线程如若不限制线程创建的数量,在峰值压力下,线程创建过多,资源耗尽,有程序崩溃的风险。
  2. 创建一个线程的时间:线程创建+任务处理+线程销毁,如果任务处理的时间占比不高,则说明大量的资源都用于了线程的创建和销毁上,因此线程池用创建好的线程循环处理任务,避免了大量的线程创建和线程销毁的时间成本。

自主创建一个线程池

线程池组成:大量线程(每个线程循环的进行任务处理)+ 任务缓冲处理
Linux:线程池 / 及如何创建一个线程池_第1张图片
线程池中的线程每次从任务队列的队首获取一个任务进行处理,线程间以此循环往复。

几个问题:

  1. 线程的入口函数都是在线程创建初传入线程的,会导致线程池中的线程进行任务处理的方式单一
  2. 线程的入口函数都一样,处理流程也就一样,只有单一的处理方式,灵活性太差

解决办法:
若任务队列中的任务,不仅仅是单纯的传入数据,并且包含了任务处理方式(入口函数),这时线程池中的线程只需要根据任务的数据和处理函数对数据进行处理,而不用关心是什么数据该如何处理。

代码

#include
#include
#include
#include
#include
using namespace std;


typedef void(*handler_t)(int data);  //定义一个任务处理函数指针
class Task{
	
public:
	//进行数据的传入,处理函数的传入
	void settask(int data,handler_t handler)
	{
		_data=data;
		_handler=handler;
	}
	//进行任务处理
	void Run()
	{
		_handler(_data);	
	}
	
private:
	int _data;
	handler_t _handler;
};

//线程池
#define Max_pthread 4
class pthreadpool{
	
public:
	pthreadpool(int max=Max_pthread)
	:_max(max)
	{
		pthread_mutex_init(&mutex,NULL);
		pthread_cond_init(&cond,NULL);
		for(int i=0;i<_max;i++)
		{
			pthread_t pthread;
			int ret=pthread_create(&pthread,NULL,thr_start,this);
			if(ret!=0)
			{
				printf("create error\n");
				exit(-1);
			}
		}
	}
	~pthreadpool()
	{
		_max=0;
		pthread_mutex_destroy(&mutex);
		pthread_cond_destroy(&cond);
	}
	bool taskpush(Task& task)
	{
		pthread_mutex_lock(&mutex);
		queue.push(task);
		pthread_mutex_unlock(&mutex);
		pthread_cond_broadcast(&cond);
		return true;
	}
	static void* thr_start(void* arg)
	{
			pthread_cond_broadcast(&p->cond);//唤醒所有线程,让他们随机去获取这个任务
		pthreadpool* p=(pthreadpool*)arg;
		while(1)
		{
			//对从任务队列中获取任务操作进行上锁,保证线程安全
			pthread_mutex_lock(&p->mutex);
			while(p->queue.empty())    //任务队列如果为空,进行线程等待
			{
				pthread_cond_wait(&p->cond,&p->mutex);	
			}
			Task task;
			task=p->queue.front();
			p->queue.pop();
			pthread_mutex_unlock(&p->mutex);//获取完任务后进行解锁
			task.Run();
		}
		
	}


private:
	pthread_mutex_t mutex;
	pthread_cond_t cond;
	std::queue<Task> queue;
	int _max;
};

定义一个任务类和线程池类

#include"test.hpp"
#include

void func1(int data)
{
	int sec=(data%3)+1;
	printf("tid:%p----data:%d----sleep:%d\n",pthread_self(),data,sec);
	sleep(sec);
}
void func2(int data)
{
	printf("tid:%p--data:%d--func2\n",pthread_self(),data);	
	sleep(1);
}


int main()
{
	pthreadpool pool;
	for(int i=0;i<10;i++)
	{
		Task task;
		if(i%2==0)
			task.settask(i,func1);	
		else
			task.settask(i,func2);
		pool.taskpush(task);
	}

	sleep(1000);
	return 0;	
}

定义了两个任务处理函数,和10个任务进行处理
运行结果:
Linux:线程池 / 及如何创建一个线程池_第2张图片
从结果可以看到共有四个线程在处理任务,总共处理了10个任务,运行正确

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