C++ 线程池的思想
生活随笔
收集整理的這篇文章主要介紹了
C++ 线程池的思想
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
參考:https://zhuanlan.zhihu.com/p/367309864
線程池原理總結(jié)
首先你要有一個(gè)隊(duì)列來(lái)保存你的任務(wù),任務(wù)就是待執(zhí)行的函數(shù),這個(gè)隊(duì)列叫做同步隊(duì)列,主要就是隊(duì)列的操作都帶上鎖實(shí)現(xiàn)線程安全。然后需要?jiǎng)?chuàng)建多個(gè)線程(可以保存在vector中,這就是線程池),每個(gè)線程創(chuàng)建的時(shí)候船用執(zhí)行函數(shù)run(),在執(zhí)行函數(shù)run()中,我們不斷取出同步隊(duì)列中的任務(wù)來(lái)執(zhí)行,直到完成所有任務(wù),并且主動(dòng)銷毀線程。
#include <mutex> #include <queue> #include <functional> #include <future> #include <thread> #include <utility> #include <vector>? #include <vector>? #include <iostream> using namespace std; // Thread safe implementation of a Queue using a std::queue template <typename T> class SafeQueue { private:std::queue<T> m_queue; //利用模板函數(shù)構(gòu)造隊(duì)列std::mutex m_mutex;// 訪問(wèn)互斥信號(hào)量 public:SafeQueue() {}SafeQueue(SafeQueue&& other) {}~SafeQueue() {}bool empty() // 返回隊(duì)列是否為空{std::unique_lock<std::mutex> lock(m_mutex); // 互斥信號(hào)變量加鎖,防止m_queue被改變return m_queue.empty();}int size(){std::unique_lock<std::mutex> lock(m_mutex); // 互斥信號(hào)變量加鎖,防止m_queue被改變return m_queue.size();}// 隊(duì)列添加元素void enqueue(T& t){std::unique_lock<std::mutex> lock(m_mutex);m_queue.emplace(t);}// 隊(duì)列取出元素bool dequeue(T& t){std::unique_lock<std::mutex> lock(m_mutex); // 隊(duì)列加鎖if (m_queue.empty()) return false;t = std::move(m_queue.front()); // 取出隊(duì)首元素,返回隊(duì)首元素值,并進(jìn)行右值引用m_queue.pop(); // 彈出入隊(duì)的第一個(gè)元素return true;} };class ThreadPool { public:bool m_shutdown; // 線程池是否關(guān)閉SafeQueue<std::function<void()>> m_queue; // 同步安全隊(duì)列std::vector<std::thread> m_threads; // 工作線程隊(duì)列std::mutex m_conditional_mutex; // 線程休眠鎖互斥變量std::condition_variable m_conditional_lock; // 線程環(huán)境鎖,可以讓線程處于休眠或者喚醒狀態(tài)ThreadPool(int threadNum = 4) :m_threads(std::vector<std::thread>(threadNum)), m_shutdown(false){for (int i = 0; i < threadNum;i++){m_threads.at(i) = std::thread(&ThreadPool::runThread,this);}}~ThreadPool(){shutdown();}void runThread(){std::function<void()> func; // 定義基礎(chǔ)函數(shù)類funcbool dequeued; // 是否正在取出隊(duì)列中元素while (!this->m_shutdown){{// 為線程環(huán)境加鎖,互訪問(wèn)工作線程的休眠和喚醒std::unique_lock<std::mutex> lock(this->m_conditional_mutex);if (this->m_queue.empty())// 如果任務(wù)隊(duì)列為空,阻塞當(dāng)前線程{this->m_conditional_lock.wait(lock); // 等待條件變量通知,開(kāi)啟線程}// 取出任務(wù)隊(duì)列中的元素dequeued = this->m_queue.dequeue(func);}// 如果成功取出,執(zhí)行工作函數(shù)if (dequeued)func();}}void shutdown(){m_shutdown = true;m_conditional_lock.notify_all(); // 通知,喚醒所有工作線程for (int i = 0; i < m_threads.size(); ++i){if (m_threads.at(i).joinable()) // 判斷線程是否在等待{m_threads.at(i).join(); // 將線程加入到等待隊(duì)列}}}//這是一個(gè)提交任務(wù)的函數(shù),用到了比較多的C++11特性template <typename F, typename... Args>auto submit(F&& f, Args&&...args) -> std::future<decltype(f(args...))>{// Create a function with bounded parameter ready to executestd::function<decltype(f(args...))()> func = std::bind(std::forward<F>(f), std::forward<Args>(args)...); // 連接函數(shù)和參數(shù)定義,特殊函數(shù)類型,避免左右值錯(cuò)誤auto task_ptr = std::make_shared<std::packaged_task<decltype(f(args...))()>>(func);std::function<void()> warpper_func = [task_ptr](){(*task_ptr)();};m_queue.enqueue(warpper_func);m_conditional_lock.notify_one();return task_ptr->get_future();} };std::mutex m_mutex; void printValue(int i) {std::unique_lock<std::mutex> lock(m_mutex);std::cout << "current thread id : " << std::this_thread::get_id() << std::endl;std::cout << "this print value : " << i << std::endl; } int main() {ThreadPool pool(3);for (int i = 0; i < 30; i++){pool.submit(printValue, i);}while (1){std::this_thread::sleep_for(std::chrono::seconds(60));}}總結(jié)
以上是生活随笔為你收集整理的C++ 线程池的思想的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 多进程fork()函数
- 下一篇: flask框架的参数传递以及MVC模式的