如何用C++实现一个线程池呢?

编程语言及工具

99人已加入

描述

C++线程池是一种多线程管理模型,把线程分成任务执行和线程调度两部分。线程任务被放入工作队列中,工作线程通常会轮询这个队列从而获取任务并执行。这种机制实现的目标是将线程的创建、销毁都由线程池来完成,节省了线程切换开销。

正常情况下,我们启动一个线程的流程需要进行以下操作:

1.申请系统资源,并创建新的线程

2.设置线程特性,如栈大小等参数

3.执行线程任务

4.结束线程,释放资源

线程池

而使用线程池则可以减少这些步骤,因为线程池中已经预先创建了一定数量的线程,这些线程处于等待状态,能够在有任务时立即响应处理。具体来说,C++线程池可以提供以下优点:

  • 对于频繁创建、删除线程的场景,使用线程池能够减轻系统负担,避免花费过高的时间和内存开销。
  • C++线程池可以通过限制线程的最大数量、保留一些线程反复利用等方式避免线程数目暴增导致的问题。
  • 线程池可以有效的处理任务队列,并优化任务处理的顺序和方式,从而使任务处理效率提高。

C++线程池在操作系统并发编程中起到了重要的作用,对于多线程服务器开发、网络编程等场景具有非常广泛的实际应用。

下面是C++实现一个简单的线程池的示例代码,该线程池可以自动管理任务队列、工作线程和互斥锁。

#include < thread >
#include < mutex >
#include < queue >
#include < condition_variable >




// 定义任务类型
typedef std::function< void() > Task;


class ThreadPool {
public:
    // 构造函数,默认启动4个工作线程
    ThreadPool(int numThreads = 4)
        : m_stop(false)
    {
        for (int i = 0; i < numThreads; ++i)
            m_workers.emplace_back(
                [this] {
                    for (;;) {
                        Task task;
                        {
                            std::unique_lock< std::mutex > lock(this- >m_mutex);
                            this- >m_cond.wait(lock, [this] { return this- >m_stop || !this- >m_tasks.empty(); });
                            if (this- >m_stop && this- >m_tasks.empty())
                                return;
                            task = std::move(this- >m_tasks.front());
                            this- >m_tasks.pop();
                        }
                        task();
                    }
                }
            );
    }


    // 删除默认构造函数
    ThreadPool() = delete;

    // 添加新的任务到任务队列中
    template< class F >
    void enqueue(F&& f)
    {
        {
            std::unique_lock< std::mutex > lock(m_mutex);
            m_tasks.emplace(std::forward< F >(f));
        }
        m_cond.notify_one();
    }




    // 停止线程池运行
    ~ThreadPool()
    {
        {
            std::unique_lock< std::mutex > lock(m_mutex);
            m_stop = true;
        }
        m_cond.notify_all();
        for (std::thread &worker: m_workers)
            worker.join();
    }
private:
    // 工作线程池
    std::vector< std::thread > m_workers;

    // 任务队列
    std::queue< Task > m_tasks;

    // 互斥锁
    std::mutex m_mutex;

    // 条件变量
    std::condition_variable m_cond;
    // 停止标志
    bool m_stop;
};

代码解析:

线程池ThreadPool包含了一个自定义类型Task,它是我们待执行的任务;还有一个std::vectorstd::thread成员m_workers,用于存放工作线程的句柄;任务队列用std::queue来实现;互斥锁使用std::mutex来管理。

构造函数:初始化时创建多个工作线程并将它们添加到工作线程池中。在每个工作线程的主循环中,用一个unique_lock判断是否有新的任务需要处理,有则从队列中取出一个任务交给该工作线程处理。没有则阻塞等待条件变量唤醒。在调用notify_one()通知任意一个线程时,不会立即被唤醒,而只是在信号量上做加一操作,至于哪个线程获得许可继续执行,则由系统决定。

enqueue()方法:可以向当前任务队列中添加一个新的任务f,并通过调用notify_one()方法通知第一个空闲线程去执行该任务。

析构函数:将停止标志m_stop设置为true,不再接受新的任务。notifyall通知每个阻塞的线程,则唤醒后就会判断该标志而终止。对于每个工作线程,调用join()方法以等待它们结束执行。

这样一个简单的C++线程池实现就完成了,你可以在项目中使用该线程池来管理你的多线程应用,提高程序效率和运行速度。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分