C++ ThreadPool

半同步半异步线程池

再处理大量并发任务的时候,如果按照传统的方式,来一个任务请求,对应一个线程来处理请求任务,大量的线程创建和销毁将消耗过多的系统资源,还增加了线程运行环境切换的开销,而通过线程池技术就可以很好地解决这些问题;线程池技术通过再系统中预先创建一定量的线程,当任务请求到来时从线程池中分配一个预先创建的线程去处理任务,线程在处理完任务之后还可以重用,不会销毁,而是等待下次任务的到来

这样,通过线程池能避免大量的线程创建和销毁动作,从而节省系统资源,这样做的一个好处是,对于多核处理器,由于线程会被分配到多个CPU,会提高并行处理的效率;另一个好处是每个线程独立阻塞,可以防止主线程被阻塞而使主流程被阻塞,导致其他的请求得不到相应的问题

线程池分为半同步半异步线程池和领导者追随者线程池,本章主要介绍半同步半异步线程池,这种线程池在实现上更简单,使用得比较多,也比较方便

在这里插入图片描述

  • 半同步半异步线程池分为三层
  1. 同步服务层:它处理来自上层的任务请求,上层的请求可能是并发的,这些请求不是马上就会被处理,而是将这些任务放到一个同步排队层中,等待处理
  2. 同步排队层:来自上层的任务请求都会加到排队层中等待处理
  3. 异步服务层,这一层中会有多个线程同时处理排队层中的任务,异步服务器从同步排队层中取出任务并行的处理

在这里插入图片描述

同步队列

template<typename T>
class  SyncQueue
{

public:
	SyncQueue(int maxSize) :m_max_Size(maxSize), m_needStop(false)
	{}
	void Put(const T& x)
	{
		Add(x);
	}
	void Put(T&& x) //const T &&x 左值常因用,编译器认为不可变,变成具名变量
 	{
		Add(std::forward<T>(x)); //保证x为右值
	}//可接收一切类型
	void Take(std::list<T>& list)
	{
		std::unique_lock<std::mutex> locker(m_mutex);
		m_notEmpty.wait(locker, [this]()->bool {return m_needStop || NotEmpty(); });
		if (m_needStop)
		{
			return;
		}
		list = std::move(m_queue); //取走全部任务
		m_notFull.notify_one();    //唤醒添加任务
	}
	void Take(T& t)
	{
		std::unique_lock<std::mutex> locker(m_mutex);
		m_notEmpty.wait(locker, [this]()->bool {return m_needStop || NotEmpty(); });
		if (m_needStop)
		{
			return;
		}
		t = m_queue.front();
		m_queue.pop_front();
		m_notFull.notify_one();
	}
	void Stop()
	{
		{
			std::unique_lock<std::mutex> locker(m_mutex);
			m_needStop = true;
		}
		m_notFull.notify_all();
		m_notEmpty.notify_all();
	}
	bool Empty()const
	{
		std::unique_lock<std::mutex> locker(m_mutex);
		return m_queue.empty();
	}
	bool Full()const
	{
		std::unique_lock<std::mutex> locker(m_mutex);
		return m_queue.size() = m_max_Size;
	}
	size_t Size()
	{
		std::unique_lock<std::mutex> locker(m_mutex);
		return m_queue.size();
	}
private:
	bool NotFull()const
	{
		bool full = m_queue.size() >= m_max_Size;
		if (full)
		{
			cout << "缓冲区已经满了  m_queue full!" << endl;
		}
		return !full;
	}
	bool NotEmpty()const
	{
		bool empty = m_queue.empty();
		if (empty)
		{
			cout << "m_queue empty!" << endl;
		}
		return !empty;
	}
	template<class F>
	void Add(F&& x) //接收任意类型 并保持值状态
	{
		std::unique_lock<std::mutex> locker(m_mutex);
		m_notFull.wait(locker, [this]()->bool {return m_needStop || NotFull(); });
		m_queue.push_back(std::forward<F>(x)); //入队
		m_notEmpty.notify_one();
	}
private:
	std::list<T> m_queue;
	mutable std::mutex m_mutex;
	std::condition_variable m_notEmpty;   //取事务等待队列
	std::condition_variable m_notFull;    //添加等待队列
	int m_max_Size;    //同步队列max
	bool m_needStop;   //是否停止
};

异步服务层

const int MaxTaskCount = 100;
class ThreadPool
{
public:
	using Task = std::function<void()>; //返回类型为空 无参
	ThreadPool(int numThreads = std::thread::hardware_concurrency()) //返回逻辑核数量
		:m_queue(MaxTaskCount)
	{
		Start(numThreads);
	}
	void Stop()
	{
		std::call_once(m_flag, [this] {StopThreadGroup(); });//终止所有线程
	}
private:
	void Start(int numThreads)
	{
		m_running = true;  //叫停线程
		for (int i = 0; i < numThreads; ++i)
		{
			m_threadgroup.push_back(std::make_shared<thread>(&ThreadPool::RunInThrea,this));
			                                               // & 告诉系统为类型成员,而不是静态成员
		}
	}
	void RunInThrea() 
	{
		while (m_running)
		{
			std::list<Task> list;
			m_queue.Take(list); //取一批事务
			for (auto& task : list)
			{
				if (!m_running)
				{
					return;
				}
				task(); //处理事务
			}
		}
	}
	void StopThreadGroup() //停止线程组线程
	{
		m_queue.Stop();
		m_running = false;
		for (auto& th : m_threadgroup)
		{
			if (th) //智能指针
			{
				th->join();
			}
		}
		m_threadgroup.clear();
	}
	std::list<std::shared_ptr<std::thread>> m_threadgroup; //线程组
	SyncQueue<Task> m_queue;
	atomic_bool m_running; //原子操作
	std::once_flag m_flag; //标记 只执行一次

};

测试代码

template<typename T>
class  SyncQueue
{

public:
	SyncQueue(int maxSize) :m_max_Size(maxSize), m_needStop(false)
	{}
	void Put(const T& x)
	{
		Add(x);
	}
	void Put(T&& x) //const T &&x 左值常因用,编译器认为不可变,变成具名变量
	{
		Add(std::forward<T>(x)); //保证x为右值
	}//可接收一切类型
	void Take(std::list<T>& list)
	{
		std::unique_lock<std::mutex> locker(m_mutex);
		m_notEmpty.wait(locker, [this]()->bool {return m_needStop || NotEmpty(); });
		if (m_needStop)
		{
			return;
		}
		list = std::move(m_queue); //取走全部任务
		m_notFull.notify_one();    //唤醒添加任务
	}
	void Take(T& t)
	{
		std::unique_lock<std::mutex> locker(m_mutex);
		m_notEmpty.wait(locker, [this]()->bool {return m_needStop || NotEmpty(); }); //空队列阻塞 不空继续运行
		if (m_needStop)
		{
			return;
		}
		t = m_queue.front();
		m_queue.pop_front();
		m_notFull.notify_one();
	}
	void Stop()
	{
		{
			std::unique_lock<std::mutex> locker(m_mutex);
			m_needStop = true;
		}
		m_notFull.notify_all();
		m_notEmpty.notify_all();
	}
	bool Empty()const
	{
		std::unique_lock<std::mutex> locker(m_mutex);
		return m_queue.empty();
	}
	bool Full()const
	{
		std::unique_lock<std::mutex> locker(m_mutex);
		return m_queue.size() = m_max_Size;
	}
	size_t Size()
	{
		std::unique_lock<std::mutex> locker(m_mutex);
		return m_queue.size();
	}
private:
	bool NotFull()const
	{
		bool full = m_queue.size() >= m_max_Size;
		if (full)
		{
			cout << "缓冲区已经满了  m_queue full!" << endl;
		}
		return !full;
	}
	bool NotEmpty()const
	{
		bool empty = m_queue.empty();
		if (empty)
		{
			cout << "m_queue empty!" << endl;
		}
		return !empty;
	}
	template<class F>
	void Add(F&& x) //接收任意类型 并保持值状态
	{
		std::unique_lock<std::mutex> locker(m_mutex);
		m_notFull.wait(locker, [this]()->bool {return m_needStop || NotFull(); });
		if (m_needStop)
		{
			return;
		}
		m_queue.push_back(std::forward<F>(x)); //入队
		m_notEmpty.notify_one();
	}
private:
	std::list<T> m_queue;
	mutable std::mutex m_mutex;
	std::condition_variable m_notEmpty;   //取事务等待队列
	std::condition_variable m_notFull;    //添加等待队列
	int m_max_Size;    //同步队列max
	bool m_needStop;   //是否停止


};

const int MaxTaskCount = 10;
class ThreadPool
{
public:
	using Task = std::function<void()>; //返回类型为空 无参
	ThreadPool(int numThreads = std::thread::hardware_concurrency()) //返回逻辑核数量
		:m_queue(MaxTaskCount)
	{
		//Start(numThreads);
	}
	~ThreadPool()
	{
		Stop();
	}
	void Stop()
	{
		std::call_once(m_flag, [this] {StopThreadGroup(); });//终止所有线程
	}
	void AddTask(Task&& task) 
	{
		m_queue.Put(task); //添加事务
	}
	void AddTask(const Task& task)
	{
		m_queue.Put(task); //添加事务
	}
	void Start(int numThreads)
	{
		m_running = true;  //叫停线程
		for (int i = 0; i < numThreads; ++i)
		{
			m_threadgroup.push_back(std::make_shared<thread>(&ThreadPool::RunInThrea, this));
			// & 告诉系统为类型成员,而不是静态成员
		}
	}
private:
	void RunInThrea()
	{
		while (m_running)
		{
			std::list<Task> list;
			m_queue.Take(list); //取一批事务
			for (auto& task : list)
			{
				if (!m_running)
				{
					return;
				}
				task(); //处理事务
			}
		}
	}
	void StopThreadGroup() //停止线程组线程
	{
		m_queue.Stop();
		m_running = false;
		for (auto& th : m_threadgroup)
		{
			if (th) //智能指针
			{
				th->join(); //等待线程停止后,将线程清除掉
			}
		}
		m_threadgroup.clear();
	}
	std::list<std::shared_ptr<std::thread>> m_threadgroup; //线程组
	SyncQueue<Task> m_queue;
	atomic_bool m_running; //原子操作
	std::once_flag m_flag; //标记 只执行一次

};


void* alloc(size_t sz)
{
	void* s = malloc(sz);
	return s;
}
void f()
{
	cout << "f" << endl;
}
void func(ThreadPool& pool)
{
	cout << "void funa" << endl;
	for (int i = 0; i < 100; ++i)
	{
		auto thdid = this_thread::get_id();
		pool.AddTask(f); //需要添加返回类型空 参数空的事务
	}
}
void TestThdPool()
{
	ThreadPool pool;
	std::thread tha(func, std::ref(pool)); //添加事务
	std::thread thb(func, std::ref(pool));
	std::this_thread::sleep_for(std::chrono::seconds(5));
	pool.Start(8);

	tha.join();
}
int main()
{
	TestThdPool();
	return 0;
}

尽管这一步可以成功的运行,但是还是确实一部分,如何对事务的参数的接收以及对返回类型的接收

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值