超簡C++11 線程池

線程池的作用:和內存池一樣,減少內核態與用戶態之間的切換

用C++11新特性實現的超簡版線程池:

#include<thread>
#include<mutex>
#include<condition_variable>
#include<vector>
#include<future>
#include<queue>
#include<iostream>

class ThreadPool {
public:
	std::queue< std::function<void()> > task_queue;
	std::vector<std::thread*> threads;
	std::mutex mtx;
	std::condition_variable cv;
	bool isWork = true;

public:
	ThreadPool(int size = 5) {
		if (size <= 0) return;
		for (int i = 0; i < size; ++i) {
			threads.push_back( new std::thread(
				[=] {
				std::function<void()> task;
					while (isWork) {
						{
							std::unique_lock<std::mutex> lock(mtx);	//進入臨界區
							
							cv.wait(lock, [this] { return !task_queue.empty(); });

							if (task_queue.empty())
								continue;
							
							task = task_queue.front();	//獲取任務
							task_queue.pop();
						} //退出臨界區,鎖自動打開

						task();		//任務完成時可執行對象task佔用的內存會自動回收
			
					}
				}
			));
			threads[i]->detach();	//啓動
		}
	}

	template<class F, class... P>
	auto insertTask(F &&f, P&&... p)-> std::future<decltype( f(p...) )> {

		using taskRetType = decltype( f(p...) );	//獲取F的返回類型

		
		auto pkt_task = std::make_shared< std::packaged_task<taskRetType()> >
			( std::bind(std::forward<F>(f), std::forward<P>(p)...) );	

		std::future<taskRetType> ret = pkt_task->get_future();	//獲取與任務關聯的future
		
		{	//進入臨界區,將任務放入任務隊列
			std::unique_lock<std::mutex> lock(mtx);
			task_queue.push( [pkt_task]{ (*pkt_task)(); } );
		}

		cv.notify_one();//喚醒被阻塞線程

		return ret;
	}
};

 

成員變量介紹:

名稱 類型 作用
task_queue std::queue< std::function<void()> > 一個隊列,隊列的元素爲一個可執行對象;該隊列會被線程池中的所有線程訪問,所以對他的讀寫要加上鎖,寫加鎖是爲了防止數據不一致,讀加鎖是爲了防止同一任務被多個線程執行;同時也應注意在任務執行完成時釋放掉可執行對象佔用的內存
threads std::vector<std::thread*> 線程池
mtx std::mutex 互斥量,相當於一把鎖
cv std::condition_variable 線程同步,喚醒或者沉睡線程

如有錯誤,請留言指出感謝!!!

 

 

發佈了9 篇原創文章 · 獲贊 0 · 訪問量 3476
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章