C++ 线程池的思想
生活随笔
收集整理的這篇文章主要介紹了
C++ 线程池的思想
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
參考:https://zhuanlan.zhihu.com/p/367309864
線程池原理總結
首先你要有一個隊列來保存你的任務,任務就是待執行的函數,這個隊列叫做同步隊列,主要就是隊列的操作都帶上鎖實現線程安全。然后需要創建多個線程(可以保存在vector中,這就是線程池),每個線程創建的時候船用執行函數run(),在執行函數run()中,我們不斷取出同步隊列中的任務來執行,直到完成所有任務,并且主動銷毀線程。
#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; //利用模板函數構造隊列std::mutex m_mutex;// 訪問互斥信號量 public:SafeQueue() {}SafeQueue(SafeQueue&& other) {}~SafeQueue() {}bool empty() // 返回隊列是否為空{std::unique_lock<std::mutex> lock(m_mutex); // 互斥信號變量加鎖,防止m_queue被改變return m_queue.empty();}int size(){std::unique_lock<std::mutex> lock(m_mutex); // 互斥信號變量加鎖,防止m_queue被改變return m_queue.size();}// 隊列添加元素void enqueue(T& t){std::unique_lock<std::mutex> lock(m_mutex);m_queue.emplace(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;} };class ThreadPool { public:bool m_shutdown; // 線程池是否關閉SafeQueue<std::function<void()>> m_queue; // 同步安全隊列std::vector<std::thread> m_threads; // 工作線程隊列std::mutex m_conditional_mutex; // 線程休眠鎖互斥變量std::condition_variable m_conditional_lock; // 線程環境鎖,可以讓線程處于休眠或者喚醒狀態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; // 定義基礎函數類funcbool dequeued; // 是否正在取出隊列中元素while (!this->m_shutdown){{// 為線程環境加鎖,互訪問工作線程的休眠和喚醒std::unique_lock<std::mutex> lock(this->m_conditional_mutex);if (this->m_queue.empty())// 如果任務隊列為空,阻塞當前線程{this->m_conditional_lock.wait(lock); // 等待條件變量通知,開啟線程}// 取出任務隊列中的元素dequeued = this->m_queue.dequeue(func);}// 如果成功取出,執行工作函數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(); // 將線程加入到等待隊列}}}//這是一個提交任務的函數,用到了比較多的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)...); // 連接函數和參數定義,特殊函數類型,避免左右值錯誤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));}}總結
以上是生活随笔為你收集整理的C++ 线程池的思想的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 多进程fork()函数
- 下一篇: flask框架的参数传递以及MVC模式的