C++线程池的实现

由于实际项目中用到过线程池,别的不多说,直接上代码:

#include <vector>
#include <queue>
#include <thread>
#include <atomic>
#include <condition_variable>
#include <future>
#include <functional>
#include <stdexcept>

#define  MAX_THREAD_NUM 256

class threadPool
{
	using Task = std::function<void()>;
	// 线程池
	std::vector<std::thread> pool;
	// 任务队列
	std::queue<Task> tasks;
	// 同步
	std::mutex m_lock;
	// 条件阻塞
	std::condition_variable cv_task;
	// 是否关闭提交
	std::atomic<bool> stoped;
	//空闲线程数量
	std::atomic<int>  idlThrNum;
	
public:
inline threadPool(unsigned short size = 4) :stoped{ false }
	{
		idlThrNum = size < 1 ? 1 : size;
		for (size = 0; size < idlThrNum; ++size)
		{   //初始化线程数量
			pool.emplace_back([this] { // 工作线程函数
				while (!this->stoped)
				{

					std::function<void()> task;
					{   // 获取一个待执行的 task
						std::unique_lock<std::mutex> lock{ this->m_lock };// unique_lock 相比 lock_guard 的好处是:可以随时 unlock() 和 lock()
						this->cv_task.wait(lock, [this] {
															return this->stoped.load() || !this->tasks.empty();
														}//end this
											); // wait 直到有 task

						if (this->stoped && this->tasks.empty())
							return;

						task = std::move(this->tasks.front()); // 取一个 task
						this->tasks.pop();
					}//end task

					idlThrNum--;
					task();
					idlThrNum++;
				}//end while

			}//end this
			);
		}//end for
	}
	inline ~threadPool()
	{
		stoped.store(true);
		cv_task.notify_all(); // 唤醒所有线程执行
		for (std::thread& thread : pool) 
		{
			    //thread.detach(); // 让线程“自生自灭”
			if (thread.joinable())
				thread.join(); // 等待任务结束, 前提:线程一定会执行完
		}
	}
	// 提交一个任务
	// 调用.get()获取返回值会等待任务执行完,获取返回值
	// 有两种方法可以实现调用类成员,
	// 一种是使用   bind: .commit(std::bind(&Dog::sayHello, &dog));
	// 一种是用 mem_fn: .commit(std::mem_fn(&Dog::sayHello), &dog)
	template < class F, class... Args>
	auto commit(F&& f, Args&&... args)->std::future < decltype(f(args...))>
	{
		if (stoped.load())    // stop == true ??
			throw std::runtime_error("commit on ThreadPool is stopped.");

		using RetType = decltype(f(args...)); // typename std::result_of<F(Args...)>::type, 函数 f 的返回值类型
		auto task = std::make_shared<std::packaged_task<RetType()> >(
			std::bind(std::forward<F>(f), std::forward<Args>(args)...)
			);    // wtf !
		std::future<RetType> future = task->get_future();
		{    // 添加任务到队列
			std::lock_guard<std::mutex> lock{ m_lock };//对当前块的语句加锁  lock_guard 是 mutex 的 stack 封装类,构造的时候 lock(),析构的时候 unlock()
			tasks.emplace(
				[task]()
		{ // push(Task{...})
				(*task)();
			}
			);
		}
		cv_task.notify_one(); // 唤醒一个线程执行

		return future;
	}

	//空闲线程数量
	int idlCount() { return idlThrNum; }

};		

用法:
int main()
{

try
{
	//threadPool executor{ 3 };
	ThreadPool2 executor{ 3 };
	A a;
	std::future<void> ff = executor.DistributeTask(fun1, 0);
	std::future<int> fg = executor.DistributeTask(gfun{}, 0);
	std::future<int> gg = executor.DistributeTask(a.Afun, 9999); //IDE提示错误,但可以编译运行
	std::future<std::string> gh = executor.DistributeTask(A::Bfun, 9998, "mult args", 123);
	std::future<std::string> fh = executor.DistributeTask([]()->std::string { std::cout << "hello, fh !  " << std::this_thread::get_id() << std::endl; return "hello,fh ret !"; });

	std::cout << " =======  sleep ========= " << std::this_thread::get_id() << std::endl;
	std::this_thread::sleep_for(std::chrono::microseconds(900));

	for (int i = 0; i < 50; i++)
	{
		executor.DistributeTask(fun1, i * 100);
	}
	std::cout << " =======  commit all ========= " << std::this_thread::get_id() << " idlsize=" << executor.idlCount() << std::endl;

	std::cout << " =======  sleep ========= " << std::this_thread::get_id() << std::endl;
	std::this_thread::sleep_for(std::chrono::seconds(3));

	ff.get(); //调用.get()获取返回值会等待线程执行完,获取返回值
	std::cout << fg.get() << "  "<<fg.get()<< "  " << fh.get().c_str() << "  " << std::this_thread::get_id() << std::endl;

	std::cout << " =======  sleep ========= " << std::this_thread::get_id() << std::endl;
	std::this_thread::sleep_for(std::chrono::seconds(3));

	std::cout << " =======  fun1,55 ========= " << std::this_thread::get_id() << std::endl;
	executor.DistributeTask(fun1, 55).get();    //调用.get()获取返回值会等待线程执行完

	std::cout << "end... " << std::this_thread::get_id() << std::endl;
	}
	catch (std::exception& e) 
	 {
		std::cout << "some unhappy happened...  " << std::this_thread::get_id() << e.what() << std::endl;
		
	 }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值