0

0

【Linux】线程池封装与介绍

爱谁谁

爱谁谁

发布时间:2025-06-27 13:46:32

|

336人浏览过

|

来源于php中文网

原创

1. 线程池介绍

  之前我们实现了线程、互斥量、条件变量以及日志的封装,现在我们可以基于以上内容来封装一个线程池。

  线程池是一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防止过分调度。可用线程数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量。

  线程池的应用场景:

需要大量的线程来完成任务,且完成任务的时间比较短。 比如WEB服务器完成网页请求这样的任务,使用线程池技术是非常合适的。因为单个任务小,而任务数量巨大,你可以想象⼀个热门网站的点击次数。 但对于长时间的任务,比如⼀个Telnet连接请求,线程池的优点就不明显了。因为Telnet会话时间比线程的创建时间大多了。 对性能要求苛刻的应用,比如要求服务器迅速响应客户请求。 接受突发性的大量请求,但不至于使服务器因此产生大量线程的应用。突发性大量客户请求,在没有线程池情况下,将产生大量线程,虽然理论上大部分操作系统线程数目最大值不是问题,短时间内产生大量线程可能使内存到达极限,出现错误。

  线程池的种类:

创建固定数量线程池,循环从任务队列中获取任务对象,获取到任务对象后,执行任务对象中的任务接口;浮动线程池,其他同上。

此处,我们选择固定线程个数的线程池。

【Linux】线程池封装与介绍
2. 线程池封装首先我们需要包含需要的头文件以及命名空间,线程池类中成员变量需要一把锁、条件变量、条件变量下等待的线程个数、存放线程的数组、线程总个数、存放任务的任务队列以及线程池是否在运行的状态表示:代码语言:javascript代码运行次数:0运行复制
#include #include #include #include #include #include "Log.hpp"#include "Mutex.hpp"#include "Cond.hpp"#include "Thread.hpp"namespace ThreadPoolModule{    using namespace LogModule;    using namespace MutexModule;    using namespace CondModule;    using namespace ThreadModule;    using thread_t = std::shared_ptr;    const static int gthreadnum = 10;    template     class ThreadPool    {    private:        int _threadnum; // 线程个数        Mutex _mutex;        Cond _cond;        int _waitnum;        std::vector _threads; // 存放线程        std::queue _tasks;           // 任务队列        bool _isrunning;    };}
在线程池类的构造函数中我们就可以创建固定数量的线程并给每个线程绑定执行的方法:代码语言:javascript代码运行次数:0运行复制
template     class ThreadPool    {    private:        bool IsEmpty() { return _tasks.empty(); }        void HandlerTask(std::string name)        {            LOG(LogLevel::INFO) << name << " HandlerTask...";            T task;            while (true)            {                {                LockGuard lockguard(_mutex);                while (IsEmpty() && _isrunning)                {                    ++_waitnum;                    _cond.Wait(_mutex);                    --_waitnum;                }                if(!_isrunning&&IsEmpty())//为了在退出之前处理完所有的任务                    break;                task = _tasks.front();                _tasks.pop();                }                //处理任务不需要加锁保护                task(name);                LOG(LogLevel::INFO) << name << " handled a task successfully...";            }            LOG(LogLevel::INFO) << name << " exit success...";        }    public:        // 是要有的,必须是私有的        ThreadPool(int threadnum = gthreadnum) : _threadnum(threadnum),                                                 _waitnum(0),                                                 _isrunning(false)        {            // 创建线程            for (int i = 0; i < _threadnum; i++)            {                _threads.emplace_back(std::make_shared(std::bind(&ThreadPool::HandlerTask, this, std::placeholders::_1))); // HandlerTask是成员函数有this参数,所以不能直接传参需要绑定                LOG(LogLevel::INFO) << _threads.back()->Name() << "Create Success...";            }            LOG(LogLevel::INFO) << "ThreadPool Construct...";        }        ~ThreadPool()        {        }    private:        int _threadnum; // 线程个数        Mutex _mutex;        Cond _cond;        int _waitnum;        std::vector _threads; // 存放线程        std::queue _tasks;           // 任务队列        bool _isrunning;    };}

如果不清楚线程类中函数与线程池中的函数接口之间是怎么相互调用的可以看看:

【Linux】线程池封装与介绍
线程Start、Stop与Wait:代码语言:javascript代码运行次数:0运行复制
        void Start()        {            if (_isrunning)                return;            _isrunning = true;            for (auto &thread : _threads)            {                thread->Start();                LOG(LogLevel::INFO) << thread->Name() << " Start Success...";            }        }        void Stop()        {            LockGuard lockguard(_mutex);            if(_isrunning)            {                // 3. 不能在入任务了                _isrunning = false; // 不工作                // 1. 让线程自己退出(要唤醒) && // 2. 历史的任务被处理完了                if(_waitnum>0)                    _cond.NotifyAll();            }        }        void Wait()        {            for (auto &thread : _threads)            {                thread->Join();                LOG(LogLevel::INFO) << thread->Name() << "Wait Success...";            }        }
线程池处理任务在上述HandlerTask中,我们还需要线程池插入新任务的方法:代码语言:javascript代码运行次数:0运行复制
bool Enqueue(const T &in)        {            // 插入任务            LockGuard lockguard(_mutex);            if (!_isrunning)                return false;            _tasks.push(in);            if (_waitnum > 0)                _cond.Notify();            return true;        }
完整实现代码语言:javascript代码运行次数:0运行复制
#pragma once#include #include #include #include #include #include "Log.hpp"#include "Mutex.hpp"#include "Cond.hpp"#include "Thread.hpp"namespace ThreadPoolModule{    using namespace LogModule;    using namespace MutexModule;    using namespace CondModule;    using namespace ThreadModule;    using thread_t = std::shared_ptr;    const static int gthreadnum = 10;    template     class ThreadPool    {    private:        bool IsEmpty() { return _tasks.empty(); }        void HandlerTask(std::string name)        {            LOG(LogLevel::INFO) << name << " HandlerTask...";            T task;            while (true)            {                {                LockGuard lockguard(_mutex);                while (IsEmpty() && _isrunning)                {                    ++_waitnum;                    _cond.Wait(_mutex);                    --_waitnum;                }                if(!_isrunning&&IsEmpty())                    break;                task = _tasks.front();                _tasks.pop();                }                //处理任务不需要加锁保护                task(name);                LOG(LogLevel::INFO) << name << " handled a task successfully...";            }            LOG(LogLevel::INFO) << name << " exit success...";        }    public:        // 是要有的,必须是私有的        ThreadPool(int threadnum = gthreadnum) : _threadnum(threadnum),                                                 _waitnum(0),                                                 _isrunning(false)        {            // 创建线程            for (int i = 0; i < _threadnum; i++)            {                _threads.emplace_back(std::make_shared(std::bind(&ThreadPool::HandlerTask, this, std::placeholders::_1))); // HandlerTask是成员函数有this参数,所以不能直接传参需要绑定                LOG(LogLevel::INFO) << _threads.back()->Name() << "Create Success...";            }            LOG(LogLevel::INFO) << "ThreadPool Construct...";        }        void Start()        {            if (_isrunning)                return;            _isrunning = true;            for (auto &thread : _threads)            {                thread->Start();                LOG(LogLevel::INFO) << thread->Name() << " Start Success...";            }        }        void Stop()        {            LockGuard lockguard(_mutex);            if(_isrunning)            {                // 3. 不能在入任务了                _isrunning = false; // 不工作                // 1. 让线程自己退出(要唤醒) && // 2. 历史的任务被处理完了                if(_waitnum>0)                    _cond.NotifyAll();            }        }        void Wait()        {            for (auto &thread : _threads)            {                thread->Join();                LOG(LogLevel::INFO) << thread->Name() << "Wait Success...";            }        }        bool Enqueue(const T &in)        {            // 插入任务            LockGuard lockguard(_mutex);            if (!_isrunning)                return false;            _tasks.push(in);            if (_waitnum > 0)                _cond.Notify();            return true;        }        ~ThreadPool()        {        }    private:        int _threadnum; // 线程个数        Mutex _mutex;        Cond _cond;        int _waitnum;        std::vector _threads; // 存放线程        std::queue _tasks;           // 任务队列        bool _isrunning;    };}
测试函数如下:

任务函数:

复古手绘美甲沙龙名片矢量模板
复古手绘美甲沙龙名片矢量模板

复古手绘美甲沙龙名片矢量模板适用于个人品牌推广、沙龙宣传材料、客户忠诚卡、预约卡、服务项目介绍、价格表、促销活动传单、社交媒体营销素材、网站着陆页、移动应用界面设计、电子邮件营销模板、线下活动邀请函、美甲教程封面、时尚博客插图、美甲产品包装设计等相关设计的AI格式素材。

下载
代码语言:javascript代码运行次数:0运行复制
#pragma once#include #include #include #include "Log.hpp"using namespace LogModule;using task_t = std::function;void Push(std::string name){    LOG(LogLevel::DEBUG) << "我是一个推送数据到服务器的一个任务, 我正在被执行" << "[" << name << "]";}

main函数:

代码语言:javascript代码运行次数:0运行复制
#include "ThreadPool.hpp"#include"Task.hpp"using namespace ThreadPoolModule;int main(){    ENABLE_CONSOLE_LOG_STRATEGY();    // ENABLE_FILE_LOG_STRATEGY();    std::unique_ptr> tp = std::make_unique>();    tp->Start();    int cnt = 10;    char c;    while (cnt)    {        tp->Enqueue(Push);         cnt--;        sleep(1);    }    tp->Stop();    sleep(3);    tp->Wait();    return 0;}
结果如下:代码语言:javascript代码运行次数:0运行复制
./thread_pool [2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [68] - Thread-1Create Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [68] - Thread-2Create Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [68] - Thread-3Create Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [68] - Thread-4Create Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [68] - Thread-5Create Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [68] - Thread-6Create Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [68] - Thread-7Create Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [68] - Thread-8Create Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [68] - Thread-9Create Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [68] - Thread-10Create Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [70] - ThreadPool Construct...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [81] - Thread-1 Start Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [81] - Thread-2 Start Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [81] - Thread-3 Start Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [81] - Thread-4 Start Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [81] - Thread-5 Start Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [81] - Thread-6 Start Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [81] - Thread-7 Start Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [81] - Thread-8 Start Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [81] - Thread-9 Start Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [81] - Thread-10 Start Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [30] - Thread-7 HandlerTask...[2025-02-04 09:54:51 ][DEBUG] [2360325] [Task.hpp] [14] - 我是一个推送数据到服务器的一个任务, 我正在被执行[Thread-7][2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [51] - Thread-7 handled a task successfully...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [30] - Thread-8 HandlerTask...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [30] - Thread-9 HandlerTask...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [30] - Thread-6 HandlerTask...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [30] - Thread-10 HandlerTask...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [30] - Thread-5 HandlerTask...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [30] - Thread-4 HandlerTask...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [30] - Thread-3 HandlerTask...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [30] - Thread-2 HandlerTask...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [30] - Thread-1 HandlerTask...[2025-02-04 09:54:52 ][DEBUG] [2360325] [Task.hpp] [14] - 我是一个推送数据到服务器的一个任务, 我正在被执行[Thread-7][2025-02-04 09:54:52 ][INFO] [2360325] [ThreadPool.hpp] [51] - Thread-7 handled a task successfully...[2025-02-04 09:54:53 ][DEBUG] [2360325] [Task.hpp] [14] - 我是一个推送数据到服务器的一个任务, 我正在被执行[Thread-8][2025-02-04 09:54:53 ][INFO] [2360325] [ThreadPool.hpp] [51] - Thread-8 handled a task successfully...[2025-02-04 09:54:54 ][DEBUG] [2360325] [Task.hpp] [14] - 我是一个推送数据到服务器的一个任务, 我正在被执行[Thread-9][2025-02-04 09:54:54 ][INFO] [2360325] [ThreadPool.hpp] [51] - Thread-9 handled a task successfully...[2025-02-04 09:54:55 ][DEBUG] [2360325] [Task.hpp] [14] - 我是一个推送数据到服务器的一个任务, 我正在被执行[Thread-6][2025-02-04 09:54:55 ][INFO] [2360325] [ThreadPool.hpp] [51] - Thread-6 handled a task successfully...[2025-02-04 09:54:56 ][DEBUG] [2360325] [Task.hpp] [14] - 我是一个推送数据到服务器的一个任务, 我正在被执行[Thread-10][2025-02-04 09:54:56 ][INFO] [2360325] [ThreadPool.hpp] [51] - Thread-10 handled a task successfully...[2025-02-04 09:54:57 ][DEBUG] [2360325] [Task.hpp] [14] - 我是一个推送数据到服务器的一个任务, 我正在被执行[Thread-5][2025-02-04 09:54:57 ][INFO] [2360325] [ThreadPool.hpp] [51] - Thread-5 handled a task successfully...[2025-02-04 09:54:58 ][DEBUG] [2360325] [Task.hpp] [14] - 我是一个推送数据到服务器的一个任务, 我正在被执行[Thread-4][2025-02-04 09:54:58 ][INFO] [2360325] [ThreadPool.hpp] [51] - Thread-4 handled a task successfully...[2025-02-04 09:54:59 ][DEBUG] [2360325] [Task.hpp] [14] - 我是一个推送数据到服务器的一个任务, 我正在被执行[Thread-3][2025-02-04 09:54:59 ][INFO] [2360325] [ThreadPool.hpp] [51] - Thread-3 handled a task successfully...[2025-02-04 09:55:00 ][DEBUG] [2360325] [Task.hpp] [14] - 我是一个推送数据到服务器的一个任务, 我正在被执行[Thread-2][2025-02-04 09:55:00 ][INFO] [2360325] [ThreadPool.hpp] [51] - Thread-2 handled a task successfully...[2025-02-04 09:55:01 ][INFO] [2360325] [ThreadPool.hpp] [54] - Thread-7 exit success...[2025-02-04 09:55:01 ][INFO] [2360325] [ThreadPool.hpp] [54] - Thread-8 exit success...[2025-02-04 09:55:01 ][INFO] [2360325] [ThreadPool.hpp] [54] - Thread-9 exit success...[2025-02-04 09:55:01 ][INFO] [2360325] [ThreadPool.hpp] [54] - Thread-6 exit success...[2025-02-04 09:55:01 ][INFO] [2360325] [ThreadPool.hpp] [54] - Thread-10 exit success...[2025-02-04 09:55:01 ][INFO] [2360325] [ThreadPool.hpp] [54] - Thread-5 exit success...[2025-02-04 09:55:01 ][INFO] [2360325] [ThreadPool.hpp] [54] - Thread-4 exit success...[2025-02-04 09:55:01 ][INFO] [2360325] [ThreadPool.hpp] [54] - Thread-3 exit success...[2025-02-04 09:55:01 ][INFO] [2360325] [ThreadPool.hpp] [54] - Thread-2 exit success...[2025-02-04 09:55:01 ][INFO] [2360325] [ThreadPool.hpp] [54] - Thread-1 exit success...[2025-02-04 09:55:04 ][INFO] [2360325] [ThreadPool.hpp] [101] - Thread-1Wait Success...[2025-02-04 09:55:04 ][INFO] [2360325] [ThreadPool.hpp] [101] - Thread-2Wait Success...[2025-02-04 09:55:04 ][INFO] [2360325] [ThreadPool.hpp] [101] - Thread-3Wait Success...[2025-02-04 09:55:04 ][INFO] [2360325] [ThreadPool.hpp] [101] - Thread-4Wait Success...[2025-02-04 09:55:04 ][INFO] [2360325] [ThreadPool.hpp] [101] - Thread-5Wait Success...[2025-02-04 09:55:04 ][INFO] [2360325] [ThreadPool.hpp] [101] - Thread-6Wait Success...[2025-02-04 09:55:04 ][INFO] [2360325] [ThreadPool.hpp] [101] - Thread-7Wait Success...[2025-02-04 09:55:04 ][INFO] [2360325] [ThreadPool.hpp] [101] - Thread-8Wait Success...[2025-02-04 09:55:04 ][INFO] [2360325] [ThreadPool.hpp] [101] - Thread-9Wait Success...[2025-02-04 09:55:04 ][INFO] [2360325] [ThreadPool.hpp] [101] - Thread-10Wait Success...
3. 线程安全的单例模式单例模式的特点

  某些类, 只应该具有⼀个对象(实例), 就称之为单例。

  在很多服务器开发场景中, 经常需要让服务器加载很多的数据 (上百G) 到内存中. 此时往往要用一个单例的类来管理这些数据。

饿汉实现方式和懒汉实现方式

[洗碗的例子]

吃完饭, 立刻洗碗, 这种就是饿汉方式. 因为下一顿吃的时候可以立刻拿着碗就能吃饭.吃完饭, 先把碗放下, 然后下⼀顿饭用到这个碗了再洗碗, 就是懒汉方式.饿汉方式实现单例模式:代码语言:javascript代码运行次数:0运行复制
template class Singleton {static T data;public:static T* GetInstance() {return &data;}};
懒汉方式实现单例模式:代码语言:javascript代码运行次数:0运行复制
template class Singleton {   static T* inst;public:   static T* GetInstance() {   if (inst == NULL)    {   inst = new T();    }   return inst;   }};
懒汉方式实现单例模式(线程安全版本):代码语言:javascript代码运行次数:0运行复制
// 懒汉模式, 线程安全template class Singleton {volatile static T* inst; // 需要设置 volatile 关键字, 否则可能被编译器优化.static std::mutex lock;public:static T* GetInstance() {if (inst == NULL) // 双重判定空指针, 降低锁冲突的概率, 提⾼性能.{ lock.lock(); // 使⽤互斥锁, 保证多线程情况下也只调⽤⼀次 new.if (inst == NULL) {inst = new T();}lock.unlock(); }return inst;}};

注意事项:

加锁解锁的位置双重 if 判定, 避免不必要的锁竞争volatile关键字防止过度优化4. 单例式线程池

  我们使用的是饿汉实现方式来实现单例线程池,首先我们需要创建静态全局的线程池指针以及锁:

代码语言:javascript代码运行次数:0运行复制
#include #include #include #include #include #include "Log.hpp"#include "Mutex.hpp"#include "Cond.hpp"#include "Thread.hpp"namespace ThreadPoolModule{    using namespace LogModule;    using namespace MutexModule;    using namespace CondModule;    using namespace ThreadModule;    using thread_t = std::shared_ptr;    const static int gthreadnum = 10;    template     class ThreadPool    {    private:        int _threadnum; // 线程个数        Mutex _mutex;        Cond _cond;        int _waitnum;        std::vector _threads; // 存放线程        std::queue _tasks;           // 任务队列        bool _isrunning;// 添加单例模式static ThreadPool *_instance;static Mutex _lock;};//在类外初始化template ThreadPool *ThreadPool::_instance = nullptr;template Mutex ThreadPool::_lock;}
然后获取线程池单例函数:代码语言:javascript代码运行次数:0运行复制
static ThreadPool *GetInstance()        {            if (_instance == nullptr)            {                LockGuard lockguard(_lock);                if (_instance == nullptr)                {                    _instance = new ThreadPool();                    _instance->Start();                }            }            LOG(LogLevel::DEBUG) << "GetInstance success...";            return _instance;        }
最后将构造函数以及Start函数设为私有以及将赋值和拷贝构造禁用。完整实现代码语言:javascript代码运行次数:0运行复制
#pragma once#include #include #include #include #include #include "Log.hpp"#include "Mutex.hpp"#include "Cond.hpp"#include "Thread.hpp"namespace ThreadPoolModule{    using namespace LogModule;    using namespace MutexModule;    using namespace CondModule;    using namespace ThreadModule;    using thread_t = std::shared_ptr;    const static int gthreadnum = 10;    template     class ThreadPool    {    private:        // 是要有的,必须是私有的        ThreadPool(int threadnum = gthreadnum) : _threadnum(threadnum),                                                 _waitnum(0),                                                 _isrunning(false)        {            // 创建线程            for (int i = 0; i < _threadnum; i++)            {                _threads.emplace_back(std::make_shared(std::bind(&ThreadPool::HandlerTask, this, std::placeholders::_1))); // HandlerTask是成员函数有this参数,所以不能直接传参需要绑定                LOG(LogLevel::INFO) << _threads.back()->Name() << "Create Success...";            }            LOG(LogLevel::INFO) << "ThreadPool Construct...";        }        bool IsEmpty() { return _tasks.empty(); }        void HandlerTask(std::string name)        {            LOG(LogLevel::INFO) << name << " HandlerTask...";            T task;            while (true)            {                {                    LockGuard lockguard(_mutex);                    while (IsEmpty() && _isrunning)                    {                        ++_waitnum;                        _cond.Wait(_mutex);                        --_waitnum;                    }                    if (!_isrunning && IsEmpty())                        break;                    task = _tasks.front();                    _tasks.pop();                }                // 处理任务不需要加锁保护                task(name);                LOG(LogLevel::INFO) << name << " handled a task successfully...";            }            LOG(LogLevel::INFO) << name << " exit success...";        }        void Start()        {            if (_isrunning)                return;            _isrunning = true;            for (auto &thread : _threads)            {                thread->Start();                LOG(LogLevel::INFO) << thread->Name() << " Start Success...";            }        }        // 赋值、拷⻉禁⽤        ThreadPool &operator=(const ThreadPool &) = delete;        ThreadPool(const ThreadPool &) = delete;    public:        static ThreadPool *GetInstance()        {            if (_instance == nullptr)            {                LockGuard lockguard(_lock);                if (_instance == nullptr)                {                    _instance = new ThreadPool();                    _instance->Start();                }            }            LOG(LogLevel::DEBUG) << "GetInstance success...";            return _instance;        }        void Stop()        {            LockGuard lockguard(_mutex);            if (_isrunning)            {                // 3. 不能在入任务了                _isrunning = false; // 不工作                // 1. 让线程自己退出(要唤醒) && // 2. 历史的任务被处理完了                if (_waitnum > 0)                    _cond.NotifyAll();            }        }        void Wait()        {            for (auto &thread : _threads)            {                thread->Join();                LOG(LogLevel::INFO) << thread->Name() << "Wait Success...";            }        }        bool Enqueue(const T &in)        {            // 插入任务            LockGuard lockguard(_mutex);            if (!_isrunning)                return false;            _tasks.push(in);            if (_waitnum > 0)                _cond.Notify();            return true;        }        ~ThreadPool()        {        }    private:        int _threadnum; // 线程个数        Mutex _mutex;        Cond _cond;        int _waitnum;        std::vector _threads; // 存放线程        std::queue _tasks;           // 任务队列        bool _isrunning;        // 单例模式        static ThreadPool *_instance;        static Mutex _lock;    };    // 在类外初始化    template     ThreadPool *ThreadPool::_instance = nullptr;    template     Mutex ThreadPool::_lock;}
测试函数:代码语言:javascript代码运行次数:0运行复制
#include #include #include #include "ThreadPool.hpp"using namespace ThreadPoolModule;using task_t = std::function;void DownLoad(std::string name){    std::cout << "this is a task" << std::endl;}int main(){    ENABLE_CONSOLE_LOG_STRATEGY();    int cnt = 10;    while (cnt)    {        ThreadPool::GetInstance()->Enqueue(DownLoad);        sleep(1);        cnt--;    }    ThreadPool::GetInstance()->Stop();    sleep(5);    ThreadPool::GetInstance()->Wait();    return 0;}
结果如下:代码语言:javascript代码运行次数:0运行复制
tutu@hecs-16648:~/linux/ThreadPool$ ./thread_pool [2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [36] - Thread-1Create Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [36] - Thread-2Create Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [36] - Thread-3Create Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [36] - Thread-4Create Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [36] - Thread-5Create Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [36] - Thread-6Create Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [36] - Thread-7Create Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [36] - Thread-8Create Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [36] - Thread-9Create Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [36] - Thread-10Create Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [38] - ThreadPool Construct...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [76] - Thread-1 Start Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [76] - Thread-2 Start Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [76] - Thread-3 Start Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [76] - Thread-4 Start Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [76] - Thread-5 Start Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [76] - Thread-6 Start Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [76] - Thread-7 Start Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [76] - Thread-8 Start Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [76] - Thread-9 Start Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [76] - Thread-10 Start Success...[2025-02-04 14:40:58 ][DEBUG] [2368011] [ThreadPool.hpp] [95] - GetInstance success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [43] - Thread-7 HandlerTask...this is a task[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [43] - Thread-8 HandlerTask...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [64] - Thread-7 handled a task successfully...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [43] - Thread-6 HandlerTask...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [43] - Thread-9 HandlerTask...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [43] - Thread-10 HandlerTask...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [43] - Thread-5 HandlerTask...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [43] - Thread-4 HandlerTask...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [43] - Thread-3 HandlerTask...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [43] - Thread-2 HandlerTask...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [43] - Thread-1 HandlerTask...[2025-02-04 14:40:59 ][DEBUG] [2368011] [ThreadPool.hpp] [95] - GetInstance success...this is a task[2025-02-04 14:40:59 ][INFO] [2368011] [ThreadPool.hpp] [64] - Thread-8 handled a task successfully...[2025-02-04 14:41:00 ][DEBUG] [2368011] [ThreadPool.hpp] [95] - GetInstance success...this is a task[2025-02-04 14:41:00 ][INFO] [2368011] [ThreadPool.hpp] [64] - Thread-7 handled a task successfully...[2025-02-04 14:41:01 ][DEBUG] [2368011] [ThreadPool.hpp] [95] - GetInstance success...this is a task[2025-02-04 14:41:01 ][INFO] [2368011] [ThreadPool.hpp] [64] - Thread-6 handled a task successfully...[2025-02-04 14:41:02 ][DEBUG] [2368011] [ThreadPool.hpp] [95] - GetInstance success...this is a task[2025-02-04 14:41:02 ][INFO] [2368011] [ThreadPool.hpp] [64] - Thread-9 handled a task successfully...[2025-02-04 14:41:03 ][DEBUG] [2368011] [ThreadPool.hpp] [95] - GetInstance success...this is a task[2025-02-04 14:41:03 ][INFO] [2368011] [ThreadPool.hpp] [64] - Thread-10 handled a task successfully...[2025-02-04 14:41:04 ][DEBUG] [2368011] [ThreadPool.hpp] [95] - GetInstance success...this is a task[2025-02-04 14:41:04 ][INFO] [2368011] [ThreadPool.hpp] [64] - Thread-5 handled a task successfully...[2025-02-04 14:41:05 ][DEBUG] [2368011] [ThreadPool.hpp] [95] - GetInstance success...this is a task[2025-02-04 14:41:05 ][INFO] [2368011] [ThreadPool.hpp] [64] - Thread-4 handled a task successfully...[2025-02-04 14:41:06 ][DEBUG] [2368011] [ThreadPool.hpp] [95] - GetInstance success...this is a task[2025-02-04 14:41:06 ][INFO] [2368011] [ThreadPool.hpp] [64] - Thread-3 handled a task successfully...[2025-02-04 14:41:07 ][DEBUG] [2368011] [ThreadPool.hpp] [95] - GetInstance success...this is a task[2025-02-04 14:41:07 ][INFO] [2368011] [ThreadPool.hpp] [64] - Thread-2 handled a task successfully...[2025-02-04 14:41:08 ][DEBUG] [2368011] [ThreadPool.hpp] [95] - GetInstance success...[2025-02-04 14:41:08 ][INFO] [2368011] [ThreadPool.hpp] [66] - Thread-8 exit success...[2025-02-04 14:41:08 ][INFO] [2368011] [ThreadPool.hpp] [66] - Thread-7 exit success...[2025-02-04 14:41:08 ][INFO] [2368011] [ThreadPool.hpp] [66] - Thread-6 exit success...[2025-02-04 14:41:08 ][INFO] [2368011] [ThreadPool.hpp] [66] - Thread-9 exit success...[2025-02-04 14:41:08 ][INFO] [2368011] [ThreadPool.hpp] [66] - Thread-10 exit success...[2025-02-04 14:41:08 ][INFO] [2368011] [ThreadPool.hpp] [66] - Thread-5 exit success...[2025-02-04 14:41:08 ][INFO] [2368011] [ThreadPool.hpp] [66] - Thread-4 exit success...[2025-02-04 14:41:08 ][INFO] [2368011] [ThreadPool.hpp] [66] - Thread-3 exit success...[2025-02-04 14:41:08 ][INFO] [2368011] [ThreadPool.hpp] [66] - Thread-2 exit success...[2025-02-04 14:41:08 ][INFO] [2368011] [ThreadPool.hpp] [66] - Thread-1 exit success...[2025-02-04 14:41:13 ][DEBUG] [2368011] [ThreadPool.hpp] [95] - GetInstance success...[2025-02-04 14:41:13 ][INFO] [2368011] [ThreadPool.hpp] [116] - Thread-1Wait Success...[2025-02-04 14:41:13 ][INFO] [2368011] [ThreadPool.hpp] [116] - Thread-2Wait Success...[2025-02-04 14:41:13 ][INFO] [2368011] [ThreadPool.hpp] [116] - Thread-3Wait Success...[2025-02-04 14:41:13 ][INFO] [2368011] [ThreadPool.hpp] [116] - Thread-4Wait Success...[2025-02-04 14:41:13 ][INFO] [2368011] [ThreadPool.hpp] [116] - Thread-5Wait Success...[2025-02-04 14:41:13 ][INFO] [2368011] [ThreadPool.hpp] [116] - Thread-6Wait Success...[2025-02-04 14:41:13 ][INFO] [2368011] [ThreadPool.hpp] [116] - Thread-7Wait Success...[2025-02-04 14:41:13 ][INFO] [2368011] [ThreadPool.hpp] [116] - Thread-8Wait Success...[2025-02-04 14:41:13 ][INFO] [2368011] [ThreadPool.hpp] [116] - Thread-9Wait Success...[2025-02-04 14:41:13 ][INFO] [2368011] [ThreadPool.hpp] [116] - Thread-10Wait Success...

相关专题

更多
js获取数组长度的方法
js获取数组长度的方法

在js中,可以利用array对象的length属性来获取数组长度,该属性可设置或返回数组中元素的数目,只需要使用“array.length”语句即可返回表示数组对象的元素个数的数值,也就是长度值。php中文网还提供JavaScript数组的相关下载、相关课程等内容,供大家免费下载使用。

556

2023.06.20

js刷新当前页面
js刷新当前页面

js刷新当前页面的方法:1、reload方法,该方法强迫浏览器刷新当前页面,语法为“location.reload([bForceGet]) ”;2、replace方法,该方法通过指定URL替换当前缓存在历史里(客户端)的项目,因此当使用replace方法之后,不能通过“前进”和“后退”来访问已经被替换的URL,语法为“location.replace(URL) ”。php中文网为大家带来了js刷新当前页面的相关知识、以及相关文章等内容

374

2023.07.04

js四舍五入
js四舍五入

js四舍五入的方法:1、tofixed方法,可把 Number 四舍五入为指定小数位数的数字;2、round() 方法,可把一个数字舍入为最接近的整数。php中文网为大家带来了js四舍五入的相关知识、以及相关文章等内容

733

2023.07.04

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

477

2023.09.01

JavaScript转义字符
JavaScript转义字符

JavaScript中的转义字符是反斜杠和引号,可以在字符串中表示特殊字符或改变字符的含义。本专题为大家提供转义字符相关的文章、下载、课程内容,供大家免费下载体验。

414

2023.09.04

js生成随机数的方法
js生成随机数的方法

js生成随机数的方法有:1、使用random函数生成0-1之间的随机数;2、使用random函数和特定范围来生成随机整数;3、使用random函数和round函数生成0-99之间的随机整数;4、使用random函数和其他函数生成更复杂的随机数;5、使用random函数和其他函数生成范围内的随机小数;6、使用random函数和其他函数生成范围内的随机整数或小数。

1011

2023.09.04

如何启用JavaScript
如何启用JavaScript

JavaScript启用方法有内联脚本、内部脚本、外部脚本和异步加载。详细介绍:1、内联脚本是将JavaScript代码直接嵌入到HTML标签中;2、内部脚本是将JavaScript代码放置在HTML文件的`<script>`标签中;3、外部脚本是将JavaScript代码放置在一个独立的文件;4、外部脚本是将JavaScript代码放置在一个独立的文件。

658

2023.09.12

Js中Symbol类详解
Js中Symbol类详解

javascript中的Symbol数据类型是一种基本数据类型,用于表示独一无二的值。Symbol的特点:1、独一无二,每个Symbol值都是唯一的,不会与其他任何值相等;2、不可变性,Symbol值一旦创建,就不能修改或者重新赋值;3、隐藏性,Symbol值不会被隐式转换为其他类型;4、无法枚举,Symbol值作为对象的属性名时,默认是不可枚举的。

553

2023.09.20

PS使用蒙版相关教程
PS使用蒙版相关教程

本专题整合了ps使用蒙版相关教程,阅读专题下面的文章了解更多详细内容。

23

2026.01.19

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
HTML教程
HTML教程

共500课时 | 4.8万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 8.5万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 0.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号