线程池 C++
时间: 2025-03-23 11:02:49 浏览: 55
### C++ 中线程池的实现与使用
#### 线程池的概念
线程池是一种多线程处理形式,它预先创建一定数量的工作线程并将其放入一个队列中等待分配任务。当有新任务提交时,线程池会从队列中取出空闲线程来执行该任务[^1]。
#### 使用标准库 `std::thread` 和其他工具构建线程池
C++11 引入了对多线程的支持,其中包括 `std::thread`、`std::mutex` 和 `std::condition_variable` 等组件。这些可以用来手动实现一个简单的线程池[^2]。
以下是基于 C++ 的一种简单线程池实现方式:
```cpp
#include <iostream>
#include <vector>
#include <queue>
#include <functional>
#include <thread>
#include <atomic>
#include <future>
class ThreadPool {
public:
explicit ThreadPool(size_t threads) : stop(false) {
for (size_t i = 0; i < threads; ++i) {
workers.emplace_back([this] {
while (true) {
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();
}
});
}
}
template<class F, class... Args>
auto enqueue(F&& f, Args&&... args) -> std::future<decltype(f(args...))> {
using return_type = decltype(f(args...));
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);
if (stop) throw std::runtime_error("enqueue on stopped ThreadPool");
tasks.emplace([task]() { (*task)(); });
}
condition.notify_one();
return res;
}
~ThreadPool() {
{
std::unique_lock<std::mutex> lock(queue_mutex);
stop = true;
}
condition.notify_all();
for (std::thread &worker: workers) worker.join();
}
private:
std::vector<std::thread> workers;
std::queue<std::function<void()>> tasks;
std::mutex queue_mutex;
std::condition_variable condition;
bool stop;
};
```
上述代码定义了一个基本的线程池类 `ThreadPool`,其中包含了多个工作线程以及用于存储待完成任务的任务队列。通过调用成员函数 `enqueue()` 可以向线程池提交新的任务,并返回一个 `std::future` 对象以便获取异步操作的结果[^3]。
#### 如何使用这个线程池?
下面是一个如何利用上面定义好的线程池来进行并发计算的小例子:
```cpp
int main() {
ThreadPool pool(4); // 创建具有四个线程的线程池
auto result1 = pool.enqueue([]{ return 42; }); // 提交第一个任务到线程池
auto result2 = pool.enqueue([]{ return 84; }); // 提交第二个任务到线程池
try {
std::cout << "Result of first job is " << result1.get() << '\n'; // 获取第一个任务结果
std::cout << "Result of second job is " << result2.get() << '\n';// 获取第二个任务结果
} catch(const std::exception& e){
std::cerr<<e.what()<<'\n';
}
return 0;
}
```
在这个示例程序里,我们初始化了一个拥有四条线程的线程池实例 `pool` 并分别往里面加入了两个不同的任务。最后通过 `.get()` 方法取得这两个任务各自的运行成果[^4]。
#### 性能考量
尽管自定义线程池能够提供灵活控制的能力,但在实际应用开发过程中也需要注意一些性能上的细节问题,比如过度频繁地创建销毁线程可能会带来较大的开销;另外还需要考虑锁竞争等因素可能影响整体效率等问题[^5]。
阅读全文
相关推荐




















