学习内容来自以下地址
http://www.cnblogs.com/qicosmos/p/4772486.html
github https://github.com/qicosmos/cosmos
有了任务队列 在程序运行之初 就预开启多个执行任务的线程 等待任务队列中传来的元素 对元素进行处理 执行完毕后 也不销毁线程 而是等待下个元素进行处理
使用std::list<std::shared_ptr<std::thread>> m_threadgroup; 变量记录线程指针 方便管理
测试例子中传递的元素类型定义为 td::function<void()> 即一个返回类型为void 无输入参数的函数
对应代码为using Task = std::function<void()>;
每当队列中添加该元素TASK 则有线程从队列中取出执行
代码如下
1 #pragma once 2 3 #include <list> 4 #include <mutex> 5 #include <thread> 6 #include <condition_variable> 7 #include <iostream> 8 9 using namespace std; 10 11 template<typename T> 12 class SyncQueue { 13 public: 14 SyncQueue(int maxSize):m_maxSize(maxSize),m_needStop(false){} 15 void Put(const T& x) { 16 Add(x); 17 } 18 void Put(T&& x) { 19 Add(std::forward<T>(x)); 20 } 21 void Take(std::list<T>& list) { 22 std::unique_lock<std::mutex> locker(m_mutex); 23 m_notEmpty.wait(locker, [this] {return m_needStop || NotEmpty(); }); 24 if (m_needStop) 25 return; 26 list = std::move(m_queue); 27 m_notFull.notify_one(); 28 } 29 30 void Take(T& t) { 31 std::unique_lock<std::mutex> locker(m_mutex); 32 m_notEmpty.wait(locker, [this] {return m_needStop || NotEmpty(); }); 33 if (m_needStop) 34 return; 35 t = m_queue.front(); 36 m_queue.pop_front(); 37 m_notFull.notify_one(); 38 } 39 40 void Stop() { 41 { 42 std::lock_guard<std::mutex> locker(m_mutex); 43 m_needStop = true; 44 } 45 m_notFull.notify_all(); 46 m_notEmpty.notify_all(); 47 } 48 49 bool Empty() { 50 std::lock_guard<std::mutex> locker(m_mutex); 51 return m_queue.empty(); 52 } 53 54 bool Full() { 55 std::lock_guard<std::mutex> locker(m_mutex); 56 return m_queue.size() == m_maxSize; 57 } 58 59 size_t Size() { 60 std::lock_guard<std::mutex> locker(m_mutex); 61 return m_queue.size(); 62 } 63 64 int Count() { 65 return m_queue.size(); 66 } 67 private: 68 bool NotFull()const { 69 bool full = m_queue.size() >= m_maxSize; 70 if (full) 71 cout << "buffer area is full,wait..." << endl; 72 return !full; 73 } 74 bool NotEmpty()const { 75 bool empty = m_queue.empty(); 76 if (empty) 77 cout << "buffer area is empty,wait... " << 78 " threadID: " << this_thread::get_id() <<endl; 79 return !empty; 80 } 81 82 template<typename F> 83 void Add(F&& x) { 84 std::unique_lock<std::mutex> locker(m_mutex); 85 m_notFull.wait(locker, [this] {return m_needStop || NotFull(); }); 86 if (m_needStop) 87 return; 88 m_queue.push_back(std::forward<F>(x)); 89 m_notEmpty.notify_one(); 90 } 91 private: 92 std::list<T> m_queue; 93 std::mutex m_mutex; 94 std::condition_variable m_notEmpty; 95 std::condition_variable m_notFull; 96 int m_maxSize; 97 bool m_needStop; 98 };
1 // ThreadPool.cpp: 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 #include <list> 6 #include <thread> 7 #include <functional> 8 #include <memory> 9 #include <atomic> 10 #include "SyncQueue.h" 11 12 const int MaxTaskCount = 100; 13 class ThreadPool { 14 using Task = std::function<void()>; 15 public: 16 ThreadPool(int numThreads = std::thread::hardware_concurrency()) :m_queue(MaxTaskCount) { 17 Start(numThreads); 18 } 19 ~ThreadPool(void) { 20 Stop(); 21 } 22 void Stop() { 23 std::call_once(m_flag, [this] {StopThreadGroup(); }); 24 } 25 void AddTask(Task&& task) { 26 m_queue.Put(std::forward<Task>(task)); 27 } 28 void AddTask(const Task& task) { 29 m_queue.Put(task); 30 } 31 32 void Start(int numThreads) { 33 m_running = true; 34 for (int i = 0; i < numThreads; i++) { 35 m_threadgroup.push_back(std::make_shared<std::thread>(&ThreadPool::RunInThread, this)); 36 } 37 } 38 private: 39 void RunInThread() { 40 while(m_running) { 41 std::list<Task> list; 42 m_queue.Take(list); 43 44 for (auto& task : list) { 45 if (!m_running) 46 return; 47 task(); 48 } 49 } 50 } 51 52 void StopThreadGroup() { 53 m_queue.Stop(); 54 m_running = false; 55 for (auto thread : m_threadgroup) { 56 if (thread) 57 thread->join(); 58 } 59 m_threadgroup.clear(); 60 } 61 std::list<std::shared_ptr<std::thread>> m_threadgroup; 62 SyncQueue<Task> m_queue; 63 atomic_bool m_running; 64 std::once_flag m_flag; 65 }; 66 67 //========================================================= 68 void TestThdPool() 69 { 70 ThreadPool pool; 71 pool.Start(2); 72 73 std::thread thd1([&pool] { 74 for (int i = 0; i < 10; i++) { 75 auto thdId = this_thread::get_id(); 76 pool.AddTask([thdId] { 77 std::cout << "thread1 id : " << thdId << std::endl; 78 }); 79 } 80 }); 81 82 std::thread thd2([&pool] { 83 for (int i = 0; i < 10; i++) { 84 auto thdId = this_thread::get_id(); 85 pool.AddTask([thdId] { 86 std::cout << "thread2 id : " << thdId << std::endl; 87 }); 88 } 89 }); 90 91 this_thread::sleep_for(std::chrono::seconds(2)); 92 getchar(); 93 pool.Stop(); 94 thd1.join(); 95 thd2.join(); 96 } 97 98 99 int main() 100 { 101 TestThdPool(); 102 return 0; 103 }
运行情况如下:
buffer area is empty,wait... threadID: 10244
buffer area is empty,wait... threadID: 8168
buffer area is empty,wait... threadID: 10136
buffer area is empty,wait... threadID: 5812
buffer area is empty,wait... threadID: 4064
buffer area is empty,wait... threadID: 7872
thread1 id : 9712buffer area is empty,wait... threadID:
8168
thread1 id : 9712
buffer area is empty,wait... threadID: 10244thread1 id : 9712
thread2 id : buffer area is empty,wait... threadID: thread2 id : 65206520
5812
thread2 id : thread1 id : thread2 id : 9712buffer area is empty,wait... threadID: thread2 id : 65206520
6520
thread2 id :
6520
thread2 id :
6520thread1 id :
40649712
thread2 id :
6520buffer area is empty,wait... threadID: thread2 id : 6520
thread1 id : 97125812
thread1 id : 9712buffer area is empty,wait... threadID: thread1 id : 10136
9712
buffer area is empty,wait... threadID: 7872thread1 id : 9712
thread2 id : 6520buffer area is empty,wait... threadID:
10244
thread1 id : 9712
buffer area is empty,wait... threadID: 8168