c++11 线程池学习笔记 (二) 线程池

学习内容来自以下地址

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 };
SyncQueue.h
  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 }
ThreadPool.cpp

运行情况如下:

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

 

posted on 2018-02-19 21:35  itdef  阅读(283)  评论(0编辑  收藏  举报

导航