线程-8-日志_线程池

打印 上一主题 下一主题

主题 1006|帖子 1006|积分 3018

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
重要看code
日志:


日志指标/属性

设计模式:策略模式
日志格式:
  1. [可读性很好的时间] [⽇志等级] [进程pid] [打印对应⽇志的⽂件名][⾏号] - 消息内容,⽀持可
  2. 变参数
  3. [2024-08-04 12:27:03] [DEBUG] [202938] [main.cc] [16] - hello world
  4. [2024-08-04 12:27:03] [DEBUG] [202938] [main.cc] [17] - hello world
  5. [2024-08-04 12:27:03] [DEBUG] [202938] [main.cc] [18] - hello world
复制代码

code


完整详细代码:https://gitee.com/whb-helloworld/112/blob/master/code/lesson32/
Log

log.hpp

  1. #pragma once
  2. #include <iostream>
  3. #include <cstdio>
  4. #include <string>
  5. #include <fstream>
  6. #include <sstream>
  7. #include <memory>
  8. #include <filesystem> //C++17
  9. #include <unistd.h>
  10. #include <time.h>
  11. #include "Mutex.hpp"
  12. namespace LogMudule
  13. {
  14.     using namespace LockModule;
  15.     // 获取一下当前系统的时间
  16.     std::string CurrentTime()
  17.     {
  18.         time_t time_stamp = ::time(nullptr);
  19.         struct tm curr;
  20.         localtime_r(&time_stamp, &curr); // 时间戳,获取可读性较强的时间信息5
  21.         char buffer[1024];
  22.         // bug
  23.         snprintf(buffer, sizeof(buffer), "%4d-%02d-%02d %02d:%02d:%02d",
  24.                  curr.tm_year + 1900,
  25.                  curr.tm_mon + 1,
  26.                  curr.tm_mday,
  27.                  curr.tm_hour,
  28.                  curr.tm_min,
  29.                  curr.tm_sec);
  30.         return buffer;
  31.     }
  32.     // 构成: 1. 构建日志字符串 2. 刷新落盘(screen, file)
  33.     //  1. 日志文件的默认路径和文件名
  34.     const std::string defaultlogpath = "./log/";
  35.     const std::string defaultlogname = "log.txt";
  36.     // 2. 日志等级
  37.     enum class LogLevel
  38.     {
  39.         DEBUG = 1,
  40.         INFO,
  41.         WARNING,
  42.         ERROR,
  43.         FATAL
  44.     };
  45.     std::string Level2String(LogLevel level)
  46.     {
  47.         switch (level)
  48.         {
  49.         case LogLevel::DEBUG:
  50.             return "DEBUG";
  51.         case LogLevel::INFO:
  52.             return "INFO";
  53.         case LogLevel::WARNING:
  54.             return "WARNING";
  55.         case LogLevel::ERROR:
  56.             return "ERROR";
  57.         case LogLevel::FATAL:
  58.             return "FATAL";
  59.         default:
  60.             return "None";
  61.         }
  62.     }
  63.     // 3. 刷新策略.
  64.     class LogStrategy
  65.     {
  66.     public:
  67.         virtual ~LogStrategy() = default;
  68.         virtual void SyncLog(const std::string &message) = 0;
  69.     };
  70.     // 3.1 控制台策略
  71.     class ConsoleLogStrategy : public LogStrategy
  72.     {
  73.     public:
  74.         ConsoleLogStrategy()
  75.         {
  76.         }
  77.         ~ConsoleLogStrategy()
  78.         {
  79.         }
  80.         void SyncLog(const std::string &message)
  81.         {
  82.             LockGuard lockguard(_lock);
  83.             std::cout << message << std::endl;
  84.         }
  85.     private:
  86.         Mutex _lock;
  87.     };
  88.     // 3.2 文件级(磁盘)策略
  89.     class FileLogStrategy : public LogStrategy
  90.     {
  91.     public:
  92.         FileLogStrategy(const std::string &logpath = defaultlogpath, const std::string &logname = defaultlogname)
  93.             : _logpath(logpath),
  94.               _logname(logname)
  95.         {
  96.             // 确认_logpath是存在的.
  97.             LockGuard lockguard(_lock);
  98.             if (std::filesystem::exists(_logpath))
  99.             {
  100.                 return;
  101.             }
  102.             try
  103.             {
  104.                 std::filesystem::create_directories(_logpath);
  105.             }
  106.             catch (std::filesystem::filesystem_error &e)
  107.             {
  108.                 std::cerr << e.what() << "\n";
  109.             }
  110.         }
  111.         ~FileLogStrategy()
  112.         {
  113.         }
  114.         void SyncLog(const std::string &message)
  115.         {
  116.             LockGuard lockguard(_lock);
  117.             std::string log = _logpath + _logname; // ./log/log.txt
  118.             std::ofstream out(log, std::ios::app); // 日志写入,一定是追加
  119.             if (!out.is_open())
  120.             {
  121.                 return;
  122.             }
  123.             out << message << "\n";
  124.             out.close();
  125.         }
  126.     private:
  127.         std::string _logpath;
  128.         std::string _logname;
  129.         // 锁
  130.         Mutex _lock;
  131.     };
  132.     // 日志类: 构建日志字符串, 根据策略,进行刷新
  133.     class Logger
  134.     {
  135.     public:
  136.         Logger()
  137.         {
  138.             // 默认采用ConsoleLogStrategy策略
  139.             _strategy = std::make_shared<ConsoleLogStrategy>();
  140.         }
  141.         void EnableConsoleLog()
  142.         {
  143.             _strategy = std::make_shared<ConsoleLogStrategy>();
  144.         }
  145.         void EnableFileLog()
  146.         {
  147.             _strategy = std::make_shared<FileLogStrategy>();
  148.         }
  149.         ~Logger() {}
  150.         // 一条完整的信息: [2024-08-04 12:27:03] [DEBUG] [202938] [main.cc] [16] + 日志的可变部分(<< "hello world" << 3.14 << a << b;)
  151.         class LogMessage
  152.         {
  153.         public:
  154.             LogMessage(LogLevel level, const std::string &filename, int line, Logger &logger)
  155.                 : _currtime(CurrentTime()),
  156.                   _level(level),
  157.                   _pid(::getpid()),
  158.                   _filename(filename),
  159.                   _line(line),
  160.                   _logger(logger)
  161.             {
  162.                 std::stringstream ssbuffer;
  163.                 ssbuffer << "[" << _currtime << "] "
  164.                          << "[" << Level2String(_level) << "] "
  165.                          << "[" << _pid << "] "
  166.                          << "[" << _filename << "] "
  167.                          << "[" << _line << "] - ";
  168.                 _loginfo = ssbuffer.str();
  169.             }
  170.             template <typename T>
  171.             LogMessage &operator<<(const T &info)
  172.             {
  173.                 std::stringstream ss;
  174.                 ss << info;
  175.                 _loginfo += ss.str();
  176.                 return *this;
  177.             }
  178.             ~LogMessage()
  179.             {
  180.                 if (_logger._strategy)
  181.                 {
  182.                     _logger._strategy->SyncLog(_loginfo);
  183.                 }
  184.             }
  185.         private:
  186.             std::string _currtime; // 当前日志的时间
  187.             LogLevel _level;       // 日志等级
  188.             pid_t _pid;            // 进程pid
  189.             std::string _filename; // 源文件名称
  190.             int _line;             // 日志所在的行号
  191.             Logger &_logger;       // 负责根据不同的策略进行刷新
  192.             std::string _loginfo;  // 一条完整的日志记录
  193.         };
  194.         // 就是要拷贝,故意的拷贝
  195.         LogMessage operator()(LogLevel level, const std::string &filename, int line)
  196.         {
  197.             return LogMessage(level, filename, line, *this);
  198.         }
  199.     private:
  200.         std::shared_ptr<LogStrategy> _strategy; // 日志刷新的策略方案
  201.     };
  202.     Logger logger;
  203. #define LOG(Level) logger(Level, __FILE__, __LINE__)
  204. #define ENABLE_CONSOLE_LOG() logger.EnableConsoleLog()
  205. #define ENABLE_FILE_LOG() logger.EnableFileLog()
  206. }
复制代码
Main.cc

  1. #include "Log.hpp"
  2. using namespace LogMudule;
  3. int main()
  4. {
  5.     ENABLE_FILE_LOG();
  6.     LOG(LogLevel::DEBUG) << "hello file";
  7.     LOG(LogLevel::DEBUG) << "hello file";
  8.     LOG(LogLevel::DEBUG) << "hello file";
  9.     LOG(LogLevel::DEBUG) << "hello file";
  10.     ENABLE_CONSOLE_LOG();
  11.     LOG(LogLevel::DEBUG) << "hello world";
  12.     LOG(LogLevel::DEBUG) << "hello world";
  13.     LOG(LogLevel::DEBUG) << "hello world";
  14.     LOG(LogLevel::DEBUG) << "hello world";
  15.     return 0;
  16. }
复制代码
ThreadPool

threadpool.hpp

  1. #pragma once
  2. #include <iostream>
  3. #include <string>
  4. #include <queue>
  5. #include <vector>
  6. #include <memory>
  7. #include "Log.hpp"
  8. #include "Mutex.hpp"
  9. #include "Cond.hpp"
  10. #include "Thread.hpp"
  11. namespace ThreadPoolModule
  12. {
  13.     using namespace LogMudule;
  14.     using namespace ThreadModule;
  15.     using namespace LockModule;
  16.     using namespace CondModule;
  17.     // 用来做测试的线程方法
  18.     void DefaultTest()
  19.     {
  20.         while (true)
  21.         {
  22.             LOG(LogLevel::DEBUG) << "我是一个测试方法";
  23.             sleep(1);
  24.         }
  25.     }
  26.     using thread_t = std::shared_ptr<Thread>;
  27.     const static int defaultnum = 5;
  28.     template <typename T>
  29.     class ThreadPool
  30.     {
  31.     private:
  32.         bool IsEmpty() { return _taskq.empty(); }
  33.         void HandlerTask(std::string name)
  34.         {
  35.             LOG(LogLevel::INFO) << "线程: " << name << ", 进入HandlerTask的逻辑";
  36.             while (true)
  37.             {
  38.                 // 1. 拿任务
  39.                 T t;
  40.                 {
  41.                     LockGuard lockguard(_lock);
  42.                     while (IsEmpty() && _isrunning)
  43.                     {
  44.                         _wait_num++;
  45.                         _cond.Wait(_lock);
  46.                         _wait_num--;
  47.                     }
  48.                     // 2. 任务队列为空 && 线程池退出了
  49.                     if(IsEmpty() && !_isrunning)
  50.                         break;
  51.                     t = _taskq.front();
  52.                     _taskq.pop();
  53.                 }
  54.                 // 2. 处理任务
  55.                 t(name); // 规定,未来所有的任务处理,全部都是必须提供()方法!
  56.             }
  57.             LOG(LogLevel::INFO) << "线程: " << name << " 退出";
  58.         }
  59.     public:
  60.         ThreadPool(int num = defaultnum) : _num(num), _wait_num(0), _isrunning(false)
  61.         {
  62.             for (int i = 0; i < _num; i++)
  63.             {
  64.                 _threads.push_back(std::make_shared<Thread>(std::bind(&ThreadPool::HandlerTask, this, std::placeholders::_1)));
  65.                 LOG(LogLevel::INFO) << "构建线程" << _threads.back()->Name() << "对象 ... 成功";
  66.             }
  67.         }
  68.         void Equeue(T &&in)
  69.         {
  70.             LockGuard lockguard(_lock);
  71.             if(!_isrunning) return;
  72.             _taskq.push(std::move(in));
  73.             if(_wait_num > 0)
  74.                 _cond.Notify();
  75.         }
  76.         void Start()
  77.         {
  78.             if(_isrunning) return;
  79.             _isrunning = true; // bug fix??
  80.             for (auto &thread_ptr : _threads)
  81.             {
  82.                 LOG(LogLevel::INFO) << "启动线程" << thread_ptr->Name() << " ... 成功";
  83.                 thread_ptr->Start();
  84.             }
  85.         }
  86.         void Wait()
  87.         {
  88.             for (auto &thread_ptr : _threads)
  89.             {
  90.                 thread_ptr->Join();
  91.                 LOG(LogLevel::INFO) << "回收线程" << thread_ptr->Name() << " ... 成功";
  92.             }
  93.         }
  94.         void Stop()
  95.         {
  96.             LockGuard lockguard(_lock);
  97.             if(_isrunning)
  98.             {
  99.                 // 3. 不能在入任务了
  100.                 _isrunning = false; // 不工作
  101.                 // 1. 让线程自己退出(要唤醒) && // 2. 历史的任务被处理完了
  102.                 if(_wait_num>0)
  103.                     _cond.NotifyAll();
  104.             }
  105.         }
  106.         ~ThreadPool()
  107.         {
  108.         }
  109.     private:
  110.         std::vector<thread_t> _threads;
  111.         int _num;
  112.         int _wait_num;
  113.         std::queue<T> _taskq; // 临界资源
  114.         Mutex _lock;
  115.         Cond _cond;
  116.         bool _isrunning;
  117.     };
  118. }
复制代码
threadpood.cc

  1. #include "ThreadPool.hpp"
  2. #include "Task.hpp"
  3. #include <memory>
  4. using namespace ThreadPoolModule;
  5. int main()
  6. {
  7.     ENABLE_CONSOLE_LOG();
  8.     // ENABLE_FILE_LOG();
  9.     std::unique_ptr<ThreadPool<task_t>> tp = std::make_unique<ThreadPool<task_t>>();
  10.     tp->Start();
  11.     int cnt = 10;
  12.     char c;
  13.     while (true)
  14.     {
  15.         std::cin >> c;
  16.         tp->Equeue(Push);
  17.         // cnt--;
  18.         // sleep(1);
  19.     }
  20.     tp->Stop();
  21.     sleep(3);
  22.     tp->Wait();
  23.     return 0;
  24. }
复制代码
task.hpp

  1. #pragma once
  2. #include <iostream>
  3. #include <string>
  4. #include <functional>
  5. #include "Log.hpp"
  6. using namespace LogMudule;
  7. using task_t = std::function<void(std::string name)>;
  8. void Push(std::string name)
  9. {
  10.     LOG(LogLevel::DEBUG) << "我是一个推送数据到服务器的一个任务, 我正在被执行" << "[" << name << "]";
  11. }
复制代码
sigThreadPool

threadpool.hpp

  1. #pragma once
  2. #include <iostream>
  3. #include <string>
  4. #include <queue>
  5. #include <vector>
  6. #include <memory>
  7. #include "Log.hpp"
  8. #include "Mutex.hpp"
  9. #include "Cond.hpp"
  10. #include "Thread.hpp"
  11. namespace ThreadPoolModule
  12. {
  13.     using namespace LogMudule;
  14.     using namespace ThreadModule;
  15.     using namespace LockModule;
  16.     using namespace CondModule;
  17.     // 用来做测试的线程方法
  18.     void DefaultTest()
  19.     {
  20.         while (true)
  21.         {
  22.             LOG(LogLevel::DEBUG) << "我是一个测试方法";
  23.             sleep(1);
  24.         }
  25.     }
  26.     using thread_t = std::shared_ptr<Thread>;
  27.     const static int defaultnum = 5;
  28.     template <typename T>
  29.     class ThreadPool
  30.     {
  31.     private:
  32.         bool IsEmpty() { return _taskq.empty(); }
  33.         void HandlerTask(std::string name)
  34.         {
  35.             LOG(LogLevel::INFO) << "线程: " << name << ", 进入HandlerTask的逻辑";
  36.             while (true)
  37.             {
  38.                 // 1. 拿任务
  39.                 T t;
  40.                 {
  41.                     LockGuard lockguard(_lock);
  42.                     while (IsEmpty() && _isrunning)
  43.                     {
  44.                         _wait_num++;
  45.                         _cond.Wait(_lock);
  46.                         _wait_num--;
  47.                     }
  48.                     // 2. 任务队列为空 && 线程池退出了
  49.                     if (IsEmpty() && !_isrunning)
  50.                         break;
  51.                     t = _taskq.front();
  52.                     _taskq.pop();
  53.                 }
  54.                 // 2. 处理任务
  55.                 t(name); // 规定,未来所有的任务处理,全部都是必须提供()方法!
  56.             }
  57.             LOG(LogLevel::INFO) << "线程: " << name << " 退出";
  58.         }
  59.         ThreadPool(const ThreadPool<T> &) = delete;
  60.         ThreadPool<T> &operator=(const ThreadPool<T> &) = delete;
  61.         ThreadPool(int num = defaultnum) : _num(num), _wait_num(0), _isrunning(false)
  62.         {
  63.             for (int i = 0; i < _num; i++)
  64.             {
  65.                 _threads.push_back(std::make_shared<Thread>(std::bind(&ThreadPool::HandlerTask, this, std::placeholders::_1)));
  66.                 LOG(LogLevel::INFO) << "构建线程" << _threads.back()->Name() << "对象 ... 成功";
  67.             }
  68.         }
  69.     public:
  70.         static ThreadPool<T> *getInstance()
  71.         {
  72.             if(instance == NULL)
  73.             {
  74.                 LockGuard lockguard(mutex);
  75.                 if(instance == NULL)
  76.                 {
  77.                     LOG(LogLevel::INFO) << "单例首次被执行,需要加载对象...";
  78.                     instance = new ThreadPool<T>();
  79.                 }
  80.             }
  81.             return instance;
  82.         }
  83.         void Equeue(T &&in)
  84.         {
  85.             LockGuard lockguard(_lock);
  86.             if (!_isrunning)
  87.                 return;
  88.             _taskq.push(std::move(in));
  89.             if (_wait_num > 0)
  90.                 _cond.Notify();
  91.         }
  92.         void Start()
  93.         {
  94.             if (_isrunning)
  95.                 return;
  96.             _isrunning = true; // bug fix??
  97.             for (auto &thread_ptr : _threads)
  98.             {
  99.                 LOG(LogLevel::INFO) << "启动线程" << thread_ptr->Name() << " ... 成功";
  100.                 thread_ptr->Start();
  101.             }
  102.         }
  103.         void Wait()
  104.         {
  105.             for (auto &thread_ptr : _threads)
  106.             {
  107.                 thread_ptr->Join();
  108.                 LOG(LogLevel::INFO) << "回收线程" << thread_ptr->Name() << " ... 成功";
  109.             }
  110.         }
  111.         void Stop()
  112.         {
  113.             LockGuard lockguard(_lock);
  114.             if (_isrunning)
  115.             {
  116.                 // 3. 不能在入任务了
  117.                 _isrunning = false; // 不工作
  118.                 // 1. 让线程自己退出(要唤醒) && // 2. 历史的任务被处理完了
  119.                 if (_wait_num > 0)
  120.                     _cond.NotifyAll();
  121.             }
  122.         }
  123.         ~ThreadPool()
  124.         {
  125.         }
  126.     private:
  127.         std::vector<thread_t> _threads;
  128.         int _num;
  129.         int _wait_num;
  130.         std::queue<T> _taskq; // 临界资源
  131.         Mutex _lock;
  132.         Cond _cond;
  133.         bool _isrunning;
  134.         static ThreadPool<T> *instance;
  135.         static Mutex mutex; //只用来保护单例
  136.     };
  137.     template<typename T>
  138.     ThreadPool<T> *ThreadPool<T>::instance = NULL;
  139.     template<typename T>
  140.     Mutex ThreadPool<T>::mutex; //只用来保护单例
  141. }
复制代码
threadpool.cc

  1. #include "ThreadPool.hpp"
  2. #include "Task.hpp"
  3. #include <memory>
  4. using namespace ThreadPoolModule;
  5. int main()
  6. {
  7.     ENABLE_CONSOLE_LOG();
  8.     ThreadPool<task_t>::getInstance()->Start();
  9.     char c;
  10.     int cnt = 5;
  11.     while (cnt)
  12.     {
  13.         // std::cin >> c;
  14.         ThreadPool<task_t>::getInstance()->Equeue(Push);
  15.         cnt--;
  16.         sleep(1);
  17.     }
  18.     ThreadPool<task_t>::getInstance()->Stop();
  19.     ThreadPool<task_t>::getInstance()->Wait();
  20.     // ENABLE_FILE_LOG();
  21.     // std::unique_ptr<ThreadPool<task_t>> tp = std::make_unique<ThreadPool<task_t>>();
  22.     // tp->Start();
  23.     // int cnt = 10;
  24.     // char c;
  25.     // while (true)
  26.     // {
  27.     //     std::cin >> c;
  28.     //     tp->Equeue(Push);
  29.     //     // cnt--;
  30.     //     // sleep(1);
  31.     // }
  32.     // tp->Stop();
  33.     // sleep(3);
  34.     // tp->Wait();
  35.     return 0;
  36. }
复制代码




板书笔记

险些没有,就不展示了

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

半亩花草

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表