在C++11中,线程池是一个非常有用的并发设计模式,主要用来管理和调度多个线程执行任务,从而提高程序的执行效率和响应速度。C++11之前,程序员通常需要依赖操作系统的API或使用第三方库来实现线程池,但C++11标准引入了更多的并发编程支持,包括线程(std::thread
),互斥锁(std::mutex
),条件变量(std::condition_variable
)等,这些新特性可以帮助我们更加容易地实现一个线程池。
线程池的基本概念和组成
线程池主要由以下几个部分组成:
- 任务队列: 存放待处理任务的队列,通常是一个先进先出的队列。
- 工作线程: 一组初始化时就创建的线程,它们循环地从任务队列中取出任务并执行。
- 互斥锁和条件变量: 用于同步和协调主线程和工作线程的执行。
实现简单的线程池
以下是一个简单的C++11线程池实现的示例:
cpp#include <vector> #include <queue> #include <thread> #include <mutex> #include <condition_variable> #include <functional> #include <iostream> class ThreadPool { private: std::vector<std::thread> workers; std::queue<std::function<void()>> tasks; std::mutex queue_mutex; std::condition_variable condition; bool stop; public: ThreadPool(size_t threads) : stop(false) { for(size_t i = 0; i < threads; ++i) workers.emplace_back( [this] { for(;;) { std::function<void()> task; { std::unique_lock<std::mutex> lock(this->queue_mutex); this->condition.wait(lock, [this] { return this->stop || !this->tasks.empty(); }); if(this->stop && this->tasks.empty()) return; task = std::move(this->tasks.front()); this->tasks.pop(); } task(); } } ); } ~ThreadPool() { { std::unique_lock<std::mutex> lock(queue_mutex); stop = true; } condition.notify_all(); for(std::thread &worker: workers) worker.join(); } template<class F, class... Args> auto enqueue(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type> { using return_type = typename std::result_of<F(Args...)>::type; auto task = std::make_shared< std::packaged_task<return_type()> >( std::bind(std::forward<F>(f), std::forward<Args>(args)...) ); std::future<return_type> res = task->get_future(); { std::unique_lock<std::mutex> lock(queue_mutex); // Don't allow enqueueing after stopping the pool if(stop) throw std::runtime_error("enqueue on stopped ThreadPool"); tasks.emplace([task](){ (*task)(); }); } condition.notify_one(); return res; } }; void print_number(int x) { std::cout << "Number: " << x << std::endl; } int main() { ThreadPool pool(4); // 创建一个有4个线程的线程池 // 添加任务到线程池 for(int i = 0; i < 10; ++i) { pool.enqueue(print_number, i); } return 0; }
说明
在上述代码中,我们创建了一个ThreadPool
类,它可以初始化指定数量的线程。工作线程不断地从任务队列中取任务执行。当调用enqueue()
方法时,它会将任务添加到队列中,并通过条件变量通知一个工作线程。
这个简单的例子展示了如何使用C++11中的各种并发和同步机制来实现一个基本的线程池。当然,实际应用中线程池的实现可能会更复杂,需要处理更多的边界情况和异常情况。
2024年6月29日 12:07 回复