• 使用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));
    	}
    }
    
    

    参考:github上star与fork过千的线程池代码,源地址如下.

    https://github.com/progschj/ThreadPool

  • 相关阅读:
    Codeforces Round #692
    【kuangbin专题一】简单搜索
    B. Beam Cannon【2014上海邀请赛】
    E. Maze【2014上海邀请赛】
    策略模式 Strategy -- 学习HeadFirst设计模式记录
    状态模式 State -- 学习HeadFirst设计模式记录
    迭代器模式 Iterator,组合模式 Composite -- 学习HeadFirst设计模式记录
    命令模式 Command – 学习HeadFirst设计模式记录
    单例模式Singleton – 学习HeadFirst设计模式记录
    工厂模式Factory – 学习HeadFirst设计模式记录
  • 原文地址:https://www.cnblogs.com/Tattoo-Welkin/p/10335254.html
Copyright © 2020-2023  润新知