线程池是一种用于管理和重用线程的技术,用于需要大量短生命周期线程的应用场景,如并发任务处理、网络服务和高性能计算等。线程池可以避免在处理短时间任务时创建与销毁线程的代价,它维护着多个线程,等待着监督管理者分配可并发执行的任务,从而提高整体性能。
实现
下面是一个简易线程池的实现:
class ThreadPool
{
public:
using Task = std::packaged_task<void()>;
ThreadPool(const ThreadPool&) = delete;
ThreadPool& operator=(const ThreadPool&) = delete;
static ThreadPool& instance()
{
static ThreadPool instance;
return instance;
}
~ThreadPool()
{
stop();
}
template <typename Func, typename... Args>
auto commit(Func&& func, Args&&... args) -> std::future<std::invoke_result_t<Func, Args...>>
{
using RetType = std::invoke_result_t<Func, Args...>;
if (stop_.load(std::memory_order_acquire))
return std::future<RetType>{};
auto task = std::make_shared<std::packaged_task<RetType()>>(
std::bind(std::forward<Func>(func), std::forward<Args>(args)...));
std::future<RetType> ret = task->get_future();
{
std::lock_guard<std::mutex> guard{mtx_};
tasks_.emplace([task = std::move(task)] { (*task)(); });
}
cond_.notify_one();
return ret;
}
int idleThreadCount()
{
return thread_num_;
}
private:
ThreadPool(unsigned int num = std::thread::hardware_concurrency()) : stop_{false}
{
thread_num_ = num <= 1 ? 2 : num;
start();
}
void start()
{
for (int i = 0; i < thread_num_; ++i)
{
pool_.emplace_back([this]() {
while (!this->stop_.load(std::memory_order_relaxed))
{
Task task;
{
std::unique_lock<std::mutex> lock{mtx_};
this->cond_.wait(lock, [this] {
return this->stop_.load(std::memory_order_relaxed) || !this->tasks_.empty();
});
if (this->tasks_.empty())
return;
task = std::move(this->tasks_.front());
this->tasks_.pop();
}
this->thread_num_--;
task();
this->thread_num_++;
}
});
}
}
void stop()
{
stop_.store(true, std::memory_order_release);
cond_.notify_all(); // 唤醒线程,避免一直挂起
for (std::thread& thr : pool_)
{
if (thr.joinable())
{
std::cout << "join thread " << thr.get_id() << std::endl;
thr.join();
}
}
}
private:
std::mutex mtx_;
std::condition_variable cond_;
std::atomic<bool> stop_;
std::atomic<int> thread_num_;
std::queue<Task> tasks_;
std::vector<std::thread> pool_;
};
利用std::packted_task来将任务统一封装成void()的形式,用户可以从commit()的future中获取到相关任务的执行结果。
用户使用时只需传入一个可调用对象和相关的参数即可。
下面是一个使用demo:
#include "threadpool.h"
int calc(int x, int y)
{
int res = x + y;
std::cout << "res = " << res << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2));
return res;
}
int main()
{
std::vector<std::future<int>> results;
for (int i = 0; i < 10; ++i)
{
results.emplace_back(ThreadPool::instance().commit(calc, i, i * 2));
}
// 等待并打印结果
for (auto&& res : results)
{
std::cout << "线程函数返回值: " << res.get() << std::endl;
}
return 0;
}
运行看下效果:

参考资料
https://subingwen.cn/cpp/threadpool/
https://gitbookcpp.llfc.club/sections/cpp/concurrent/concpp07.html?h=%E7%BA%BF%E7%A8%8B%E6%B1%A0
https://subingwen.cn/cpp/async/
1953

被折叠的 条评论
为什么被折叠?



