C++简易线程池的实现

线程池是一种用于管理和重用线程的技术,用于需要大量短生命周期线程的应用场景,如并发任务处理、网络服务和高性能计算等。线程池可以避免在处理短时间任务时创建与销毁线程的代价,它维护着多个线程,等待着监督管理者分配可并发执行的任务,从而提高整体性能。

实现

下面是一个简易线程池的实现:

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/

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值