C++11 线程池 —— 能够自动管理线程数量

简介

最近学习C++11 的thread并发编程,但是里面的内容还不是很全面,线程池和一些信号量也没有,之前的笔记linux网络编程学习笔记——线程池是基于纯c的linux版本的,想着基于C++11 thread 和其新特性做一个类似的线程池组件以便于学习,大部分借鉴github上一个threadpool,只是这个没有线程池管理,无法根据情况自动扩容和缩减线程数量,进行了二次修改。

关于线程池的原理网上一大把就不详细说明了,直接上源码。

SafeQueue.h

#include <mutex>
#include <queue>

// Thread safe implementation of a Queue using an std::queue
template <typename T>
class SafeQueue {
   
private:
	std::queue<T> m_queue;
	std::mutex m_mutex;
public:
	SafeQueue() {
   

	}

	SafeQueue(SafeQueue& other) {
   
		//TODO:
	}

	~SafeQueue() {
   

	}
	
	bool empty() {
   
		std::unique_lock<std::mutex> lock(m_mutex);
		return m_queue.empty();
	}

	int size() {
   
		std::unique_lock<std::mutex> lock(m_mutex);
		return m_queue.size();
	}

	void enqueue(T& t) {
   
		std::unique_lock<std::mutex> lock(m_mutex);
		m_queue.push(t);
	}

	bool dequeue(T& t) {
   
		std::unique_lock<std::mutex> lock(m_mutex);

		if (m_queue.empty()) {
   
			return false;
		}
		t = std::move(m_queue.front());

		m_queue.pop();
		return true;
	}
};

这部分代码没什么好说的,就是对一个队列进行了二次封装的模板类保证线程安全用于存放任务队列。

ThreadPool.h

#include <functional>
#include <future>
#include <mutex>
#include <queue>
#include <thread>
#include <utility>
#include <vector>
#include <chrono>

#include "SafeQueue.h"

class ThreadPool {
   
private:
	class ThreadWorker {
   
	private:
		int m_id;
		ThreadPool * m_pool;
	public:
		ThreadWorker(ThreadPool * pool, const int id)
			: m_pool(pool), m_id(id) {
   
		}

		void operator()() {
   
			std::function<void()> func;
			bool dequeued;
			
			while (!m_pool->m_shutdown) {
   
				{
   
					std::unique_lock<std::mutex> lock(m_pool->m_conditional_mutex);

					while (m_pool->m_queue.empty() && !m_pool->m_shutdown)
					{
   
						
						if (m_pool->wait_exit_thr_num > 0)
						{
   
							m_pool->wait_exit_thr_num--;

							if (m_pool->live_thr_num > m_pool->min_thr_num)
							{
   
								m_pool->live_thr_num--;
								return;
							}
						}
						else
						{
   
							m_pool->m_conditional_lock.wait(lock);
						}
					}		
				}

				dequeued = m_pool->m_queue.dequeue(func);

				if (dequeued) {
   
					m_pool->busy_thr_num++;
					func();
					m_pool->busy_thr_num--;
				}
			}
			
		}
	};

	//
	void adjust_thread(void)
	{
   
		while (!m_shutdown)
		{
   
			std::this_thread::sleep_for(period);
			std::unique_lock<std::mutex> lock(m_conditional_mutex);
			int queue_size = m_queue.size();
			int live_thr_num = this->live_thr_num;
			lock.unlock();
			int busy_thr_num = this->busy_thr_num;

			if (queue_size >= min_wait_task_num && live_thr_num < max_thr_num) {
   
				lock.lock();
				int add = 0;
				for (int i = 0; i < max_thr_num && add < default_thread_vary
					&& live_thr_num < max_thr_num; i
  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
线程池是一种重用线程的机制,通过管理线程的生命周期、线程数量和任务的调度,实现高效的多线程处理。线程池的主要目的是减少线程创建和销毁的开销,提高线程的重用性和整体性能。 线程池的实现可以采用依赖于具体语言和平台的不同方式。在C语言中,我们可以通过以下步骤来实现一个简单的线程池: 1. 定义线程池的数据结构。可以使用结构体来存储线程池的属性,如线程数量、互斥锁、条件变量等。 2. 初始化线程池。在初始化过程中,需要初始化线程池的属性,包括线程数量、互斥锁和条件变量,并创建指定数量线程。 3. 定义工作任务。工作任务是线程池中的每个线程需要执行的具体任务。可以定义函数指针或结构体来表示工作任务。 4. 实现线程池的调度逻辑。在调度逻辑中,需要设置线程池中每个线程的状态,以及获取任务并分发给空闲线程进行处理。 5. 实现线程池的销毁操作。在销毁操作中,需要释放线程池中的资源,包括线程、互斥锁和条件变量。 通过以上步骤,我们可以实现一个简单的线程池。在实际应用中,还可以对线程池进行扩展,如设置最大线程数量、超时处理、任务队列等,以更好地满足实际需求。 线程池的优点是可以提高多线程程序的性能和效率,避免了线程创建和销毁的开销,提高了线程的重用性。同时,线程池还可以进行任务调度和管理,使得多线程的编程更加方便和可控。它可以适用于需要处理大量耗时任务的应用场景,如服务器程序和并行计算等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值