使用C++11实现线程池的两种方法
概述:什么是线程池?
因为程序边运行边创建线程是比较耗时的,所以我们通过池化的思想:在程序开始运行前创建多个线程,这样,程序在运行时,只需要从线程池中拿来用就可以了.大大提高了程序运行效率.
如何实现:
一般线程池都会有以下几个部分构成:
1. 线程池管理器(ThreadPoolManager):用于创建并管理线程池
2. 工作线程(WorkThread): 线程池中线程
3. 任务队列:用于存放没有处理的任务。提供一种缓冲机制。
4. 用于添加任务的接口
总的来讲,就是先创建几个线程,然后这些线程等待任务队列,不为空拿出任务执行即可(任务可以是对象,也可以是某个函数).
第一种实现:
#ifndef _THREADPOOL_H #define _THREADPOOL_H #include <vector> #include <queue> #include <thread> #include <iostream> #include <stdexcept> #include <condition_variable> #include <memory> //unique_ptr const int MAX_THREADS = 1000; //最大线程数目 template <typename T> class threadPool { public: /*默认开一个线程*/ threadPool(int number = 1); ~threadPool(); /*往请求队列<task_queue>中添加任务<T *>*/ bool append(T *request); private: /*工作线程需要运行的函数,不断的从任务队列中取出并执行*/ static void *worker(void *arg); void run(); private: std::vector<std::thread> work_threads; /*工作线程*/ std::queue<T *> tasks_queue; /*任务队列*/ std::mutex queue_mutex; std::condition_variable condition; /*必须与unique_lock配合使用*/ bool stop; }; template <typename T> threadPool<T>::threadPool(int number) : stop(false) { if (number <= 0 || number > MAX_THREADS) throw std::exception(); for (int i = 0; i < number; i++) { std::cout << "创建第" << i << "个线程 " << std::endl; /* std::thread temp(worker, this); 不能先构造再插入 */ work_threads.emplace_back(worker, this); } } template <typename T> inline threadPool<T>::~threadPool() { /*世上最大 bug 就是因为我写的这个.shit */ //work_threads.clear(); { std::unique_lock<std::mutex> lock(queue_mutex); stop = true; } condition.notify_all(); for (auto &ww : work_threads) ww.join(); } template <typename T> bool threadPool<T>::append(T *request) { /*操作工作队列时一定要加锁,因为他被所有线程共享*/ queue_mutex.lock(); tasks_queue.push(request); queue_mutex.unlock(); condition.notify_one(); //线程池添加进去了任务,自然要通知等待的线程 return true; } template <typename T> void *threadPool<T>::worker(void *arg) { threadPool *pool = (threadPool *)arg; pool->run(); return pool; } template <typename T> void threadPool<T>::run() { while (!stop) { std::unique_lock<std::mutex> lk(this->queue_mutex); /* unique_lock() 出作用域会自动解锁 */ this->condition.wait(lk, [this] { return !this->tasks_queue.empty(); }); //如果任务队列不为空,就停下来等待唤醒 if (this->tasks_queue.empty()) { continue; } else { T *request = tasks_queue.front(); tasks_queue.pop(); if (request) request->process(); } } } #endif
测试代码:
#include "threadPool.h" #include<string> using namespace std; class Task { public: void process() { cout << "run........." << endl; } }; int main(void) { threadPool<Task> pool(6); std::string str; while (1) { Task *tt = new Task(); //使用智能指针 pool.append(tt); delete tt; } }
第二种实现(适用于需传参,需要将非静态线程函数写在类中的情况):
#ifndef _THREADPOOL_H #define _THREADPOOL_H #include <vector> #include <queue> #include <thread> #include <iostream> #include <stdexcept> #include <condition_variable> #include <memory> //unique_ptr #include <functional> const int MAX_THREADS = 1000; //最大线程数目 typedef std::function<void(void)> Task; class threadPool { public: /*默认开一个线程*/ threadPool(int number = 1); ~threadPool(); /*往请求队列<task_queue>中添加任务<T *>*/ bool append(Task task); private: /*工作线程需要运行的函数,不断的从任务队列中取出并执行*/ static void *worker(void *arg); void run(); private: std::vector<std::thread> work_threads; /*工作线程*/ std::queue<Task> tasks_queue; /*任务队列*/ std::mutex queue_mutex; std::condition_variable condition; /*必须与unique_lock配合使用*/ bool stop; }; threadPool::threadPool(int number) : stop(false) { if (number <= 0 || number > MAX_THREADS) throw std::exception(); for (int i = 0; i < number; i++) { std::cout << "创建第" << i << "个线程 " << std::endl; work_threads.emplace_back(threadPool::worker, this); } } inline threadPool::~threadPool() { { std::unique_lock<std::mutex> lock(queue_mutex); stop = true; } condition.notify_all(); for (auto &ww : work_threads) ww.join(); } bool threadPool::append(Task task) { /*操作工作队列时一定要加锁,因为他被所有线程共享*/ queue_mutex.lock(); tasks_queue.push(task); queue_mutex.unlock(); condition.notify_one(); //线程池添加进去了任务,自然要通知等待的线程 return true; } void *threadPool::worker(void *arg) { threadPool *pool = (threadPool *)arg; pool->run(); return pool; } void threadPool::run() { while (!stop) { std::unique_lock<std::mutex> lk(this->queue_mutex); /* unique_lock() 出作用域会自动解锁 */ this->condition.wait(lk, [this] { return !this->tasks_queue.empty(); }); //如果任务队列不为空,就停下来等待唤醒 if (this->tasks_queue.empty()) { continue; } else { Task task = tasks_queue.front(); tasks_queue.pop(); task(); } } } #endif
测试代码:
#include "threadPool_2.h" using namespace std; class Test { public: void process_no_static_bind(const int i, const int j) /*推荐使用*/ { cout << "bind: i==" << i << " " << "j==" << j << endl; } }; int main(void) { threadPool pool(6); Test tt_bind; while (true) { pool.append(std::bind(&Test::process_no_static_bind, &tt_bind, 3, 4)); } }