From 2724d791c5aed81a944c786b1a32e123642b35ee Mon Sep 17 00:00:00 2001 From: AdamSmith Date: Fri, 20 Nov 2020 10:06:01 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=BA=BF=E7=A8=8B=E6=B1=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 7 ++- ThreadPool/HeapQueue.hpp | 79 ++++++++++++++++++++++++++ ThreadPool/ThreadPool.hpp | 115 ++++++++++++++++++++++++++++++++++++++ ThreadPool/main.cpp | 24 ++++++++ 4 files changed, 224 insertions(+), 1 deletion(-) create mode 100644 ThreadPool/HeapQueue.hpp create mode 100644 ThreadPool/ThreadPool.hpp create mode 100644 ThreadPool/main.cpp diff --git a/README.md b/README.md index 9a1f805..02fed9e 100644 --- a/README.md +++ b/README.md @@ -19,4 +19,9 @@ 参考内容 * CoverEars(迅雷不及掩耳,Qt版多线程下载器) https://github.com/xj361685640/CoverEars-Qt -![](./MultiplethreadDownload/screenshot.png) \ No newline at end of file +![](./MultiplethreadDownload/screenshot.png) + +# C++ 相关DEMO +用来测试练习C++技术的。 + +C++实现的线程池,有些问题 [点击查看](./ThreadPool) \ No newline at end of file diff --git a/ThreadPool/HeapQueue.hpp b/ThreadPool/HeapQueue.hpp new file mode 100644 index 0000000..f4b0605 --- /dev/null +++ b/ThreadPool/HeapQueue.hpp @@ -0,0 +1,79 @@ +#pragma once +#include +#include + +template< + typename T, + typename Array=std::vector, + typename compare_T=std::less +> +class HeapQueue +{ +public: + HeapQueue() { elements.clear(); } + + bool empty() { return elements.size() == 0; } + + T front() { return elements[0]; } + + /** + * 入列,并向上调整 + */ + void push(const T &val) + { + elements.push_back(val); + up_update(); + } + + /** + * 出列,弹出栈顶元素 + */ + void pop() { + if (empty()) + return ; + int n = elements.size(); + std::swap(elements[n-1], elements[0]); + elements.pop_back(); + down_update(); + return ; + } + +private: + /** + * 向上调整 + */ + void up_update() + { + int ind = elements.size(); + while (ind > 1 && compare(elements[ind / 2 - 1], elements[ind - 1])) + { + std::swap(elements[ind / 2 - 1], elements[ind - 1]); + ind /= 2; + } + } + + /** + * 向下调整 + */ + void down_update() + { + int ind = 0, n = elements.size(); + while (ind * 2 + 1 < n) + { + int tind = ind; + if (compare(elements[tind], elements[ind * 2 + 1])) + tind = ind * 2 + 1; + + if (ind * 2 + 2 < n && compare(elements[tind], elements[ind * 2 + 2])) + tind = ind * 2 + 2; + + if (ind == tind) + break; + std::swap(elements[ind], elements[tind]); + ind = tind; + } + } + + Array elements; + compare_T compare; +}; \ No newline at end of file diff --git a/ThreadPool/ThreadPool.hpp b/ThreadPool/ThreadPool.hpp new file mode 100644 index 0000000..dda70f7 --- /dev/null +++ b/ThreadPool/ThreadPool.hpp @@ -0,0 +1,115 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include + +class Task +{ +public: + template + Task(Func&& f, Args&& ...args) + { + func = std::bind(std::forward(f), std::forward(args)...); + } + + void run() + { + std::cout << "开始运行任务函数!" << std::endl; + func(); + return; + } + +private: + std::function func; +}; + +/** + * 将线程池改成模板类,让任务队列可配置 + */ +template> +class ThreadPool +{ +public: + ThreadPool(size_t n) + { + + for (int i = 0; i < n; i++) { + threads.push_back(new std::thread( + &ThreadPool::thread_worker, this + )); + } + } + ~ThreadPool() + { + { + std::unique_lock lock(m_mutex); + is_running = false; // 线程池即将要销毁停止工作了 + } + m_cond.notify_all(); + for(auto &worker : threads) { + worker->join(); + delete worker; + worker = nullptr; + } + } + + /** + * 工作线程入口函数,在取任务和执行任务之间做循环, + * 直到整个线程池停止工作、被销毁为止 + */ + void thread_worker() + { + while (is_running) { + Task *t = getOneTask(); + if (t == nullptr) { + std::cout << "获取任务失败 调用了个寂寞" << std::endl; + return; + } else { + std::cout << "拿到了任务,耶耶耶" << std::endl; + } + t->run(); + } + } + + Task *getOneTask() + { + { + // 进入线程临界区时加锁 + std::unique_lock lock(m_mutex); + // 等待任务 + m_cond.wait(lock, [this](){ + return is_running && tasks.empty(); + }); + Task *t = nullptr; + if (is_running) { + t = tasks.front(); + tasks.pop(); + } + return t; + } + } + + void addOneTask(Task *t) + { + std::unique_lock lock(m_mutex); + // 线程池停止,不允许再添加新的任务 + if (!is_running) { + return; + } + tasks.push(t); + std::cout << "添加任务成功!"; + m_cond.notify_one(); + } + +private: + std::vector threads; + bool is_running = true; + QueueType tasks; + std::mutex m_mutex; + std::condition_variable m_cond; +}; \ No newline at end of file diff --git a/ThreadPool/main.cpp b/ThreadPool/main.cpp new file mode 100644 index 0000000..54a673f --- /dev/null +++ b/ThreadPool/main.cpp @@ -0,0 +1,24 @@ +#include "ThreadPool.hpp" +#include + +void func(int a, int b) +{ + std::cout << a << "+" << b << "=" << a + b << std::endl; + return; +} + +/** + * 这个运行还是有点问题的,会卡顿,应该是线程退出的问题 + * 不像另外一个线程池,能够很快地运行 + */ +int main(int argc, char const *argv[]) +{ + std::cout << "测试输出!" << std::endl; + ThreadPool<> pool(5); + Task t1(func, 3, 4), t2(func, 5, 6); + + pool.addOneTask(&t1); + pool.addOneTask(&t2); + + return 0; +}