[C++]基于C++11的线程池

测试环境

lin@debian:~$ uname -a
Linux debian 6.1.0-23-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.99-1 (2024-07-15) x86_64 GNU/Linux

lin@debian:~$ g++ --version
g++ (Debian 12.2.0-14) 12.2.0
Copyright (C) 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

C++标准

-std >= c++11

参考

爱编程的大丙 -> 异步线程池(基于C++11实现)
链接:

https://subingwen.cn/cpp/threadpool/

实现

头文件

ThreadPool.h:

#ifndef INC_THREADPOOL_H
#define INC_THREADPOOL_H 1

#include <thread>
#include <functional>

namespace ThreadPool {
	int Init(const int min_threads_nums, const int max_threads_nums);
	int Destory();
	int AddTask(std::function<void()> &&task);

	template <typename Func, typename...Args>
	inline int AddTask(Func &&func, Args&&...args) {
        auto task = std::bind(std::forward<Func>(func), std::forward<Args>(args)...);
        return AddTask(std::function<void()>(std::move(task)));
	}
}
#endif

源文件

ThreadPool.cpp:

#include <map>
#include <mutex>
#include <queue>
#include <atomic>
#include <condition_variable>

#include "ThreadPool.h"

class CThreadPoolMng {
private:
	const int m_min_threads;
	const int m_max_threads;
	std::thread *m_manager;
	std::map<std::thread::id, std::thread> m_workers;
	std::vector<std::thread::id> m_ids;
	std::atomic<bool> m_stop;
	std::atomic<int> m_cur_threads;
	std::atomic<int> m_idle_threads;
	std::atomic<int> m_exit_nums;
	std::queue<std::function<void()>> m_tasks;
	std::mutex m_ids_mtx;
	std::mutex m_queue_mtx;
	std::condition_variable m_conditions;
private:
	void worker_func() {
		while (m_stop.load() != true || m_tasks.empty() != true) {
			std::function<void()> task = nullptr;
			{
				std::unique_lock<std::mutex> lock(m_queue_mtx);
				while (m_tasks.empty()) {
					m_conditions.wait(lock);
					if (m_exit_nums.load() > 0) {
						std::lock_guard<std::mutex> lck(m_ids_mtx);
						if (m_exit_nums.load() <= 0) {
							continue;
						}
						m_exit_nums--;
						m_ids.emplace_back(std::this_thread::get_id());
						std::printf("destory thread...\n");
						m_idle_threads--;
						return;
					}
					if (m_tasks.empty() && m_stop.load()) {
						std::printf("exit thread...\n");
						m_idle_threads--;
						return;
					}
				}

				if (m_tasks.empty() != true) {
					task = std::move(m_tasks.front());
					m_tasks.pop();
				}
			}
			if (task) {
				m_idle_threads--;
				task();
				m_idle_threads++;
			}
		}
	}
	void manager_func() {
		// 创建工作线程
		for (int i = 0; i < m_min_threads; i++) {
			std::thread t(&CThreadPoolMng::worker_func, this);
			m_workers.insert(std::make_pair(t.get_id(), std::move(t)));
			m_cur_threads++;
			m_idle_threads++;
		}
		while (m_stop.load() != true || m_tasks.empty() != true) {
			if (m_min_threads == m_max_threads) {
				std::this_thread::sleep_for(std::chrono::seconds(10));
				continue;
			}
			const int idle = m_idle_threads.load();													// 闲置线程
			const int current = m_cur_threads.load();												// 当前线程
			// 任务过多
			if (0 == idle && current < m_max_threads && m_tasks.empty() != true) {
				std::thread t(&CThreadPoolMng::worker_func, this);
				m_workers.insert(std::make_pair(t.get_id(), std::move(t)));
				std::printf("add thread...\n");
				m_cur_threads++;
				m_idle_threads++;
				continue;
			}
			// 线程过多
			const int delnum = ((current - m_min_threads) >= 5 ? 5 : (current - m_min_threads));	// 当线程池数过多时, 删除的线程数
			const bool more_cond = (idle > current / 2 && current - delnum >= m_min_threads);		// 线程是否过多判断条件
			if (delnum <= 0 || more_cond != true) {
				std::this_thread::sleep_for(std::chrono::seconds(1));
				continue;
			}
			m_exit_nums += delnum;
			m_conditions.notify_all();
			std::this_thread::sleep_for(std::chrono::milliseconds(10));
			std::lock_guard<std::mutex> lck(m_ids_mtx);
			for (const auto &id : m_ids) {
				auto it = m_workers.find(id);
				if (m_workers.end() == it) {
					continue;
				}
				if (it->second.joinable()) {
					it->second.join();
				}
				m_workers.erase(it);
				m_cur_threads--;
			}
			m_ids.clear();
			std::this_thread::sleep_for(std::chrono::seconds(10));
			continue;
		}

		// 销毁工作线程
		for (auto &it : m_workers) {
			std::thread &t = it.second;
			if (t.joinable()) {
				t.join();
			}
		}
	}
public:
	CThreadPoolMng(const int min_threads_nums, const int max_threads_nums) : m_min_threads(min_threads_nums), m_max_threads(max_threads_nums) {
		m_stop = false;
		m_idle_threads = m_cur_threads = m_exit_nums = 0;
		m_manager = new std::thread(&CThreadPoolMng::manager_func, this);
	}
	~CThreadPoolMng() {
		m_stop = true;
		m_conditions.notify_all();
		if (m_manager->joinable()) {
			m_manager->join();
		}
		delete m_manager;
	}
	void add_task(std::function<void()> &&task) {
		if (m_stop.load() == true) {
			return;
		}
		else {
			std::lock_guard<std::mutex> lock(m_queue_mtx);
			m_tasks.emplace(std::move(task));
		}
		m_conditions.notify_all();
	}
};

static std::mutex s_threadinit_lock;
static CThreadPoolMng *s_threadpoolmng = nullptr;

int ThreadPool::Init(const int min_threads_nums, const int max_threads_nums) {
	if (min_threads_nums < 1 || max_threads_nums < min_threads_nums) {
		return -1;
	}
	if (s_threadpoolmng != nullptr) {
		return -2;
	}
	std::lock_guard<std::mutex> lock(s_threadinit_lock);
	if (s_threadpoolmng != nullptr) {
		return -3;
	}
	s_threadpoolmng = new CThreadPoolMng(min_threads_nums, max_threads_nums);
	return 0;
}

int ThreadPool::Destory() {
	if (nullptr == s_threadpoolmng) {
		return -1;
	}
	std::lock_guard<std::mutex> lock(s_threadinit_lock);
	if (nullptr == s_threadpoolmng) {
		return -2;
	}
	delete s_threadpoolmng;
	s_threadpoolmng = nullptr;
	return 0;
}

int ThreadPool::AddTask(std::function<void()> &&task) {
	if (nullptr == s_threadpoolmng) {
		return -1;
	}
	s_threadpoolmng->add_task(std::move(task));
	return 0;
}

demo

#include <cstdio>
#include <iostream>

#include "ThreadPool.h"

void calc(const int x, const int y) {
	const int res = x + y;
	std::printf("in %s::%d:: res = [%d].\n", __func__, __LINE__, res);
	std::this_thread::sleep_for(std::chrono::seconds(10));
}

int test(const int i) {
	std::printf("in %s::%d:: i = [%d].\n", __func__, __LINE__, i);
	std::this_thread::sleep_for(std::chrono::seconds(10));
	return 0;
}

int main() {
	ThreadPool::Init(4, 100);
	for (int i = 0; i < 100; i++) {
		ThreadPool::AddTask(calc, i, i * 2);
	}
	for (int i = 0; i < 100; i++) {
		ThreadPool::AddTask(test, i);
	}
	std::getchar();             // 测试通过管理者线程检测到工作线程过多时退出工作线程
	ThreadPool::Destory();
	std::getchar();             // 测试通过delete管理者线程时退出工作线程, 一般数量为min_thread_nums
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值