当前位置:   article > 正文

LINUX:懒汉单例模式线程池

LINUX:懒汉单例模式线程池

目录

1.什么是线程池,线程池的优势

2.懒汉和饿汉模式

3.单例模式

4.日志系统

5.线程池


1.什么是线程池,线程池的优势

创建一个线程,就是要这个线程去完成某种任务的。

池化技术就是,提前创建一批线程,有任务这一批线程就会执行。而不是有任务的时候在去创建线程。

池化技术有着更高的效率,因为线程都是提前创建好的,直接执行任务。

2.懒汉和饿汉模式

懒汉和饿汉模式是一种设计模式

懒汉模式:

例:进程需要一块内存资源,什么时候真正用到了这块内存时,我在去创建而不是提前创建。

这种模式的优点就是,启动的更快,程序启动时,数据要加载到内存,懒汉就是延时加载,用的时候在加载。

3.单例模式

就是某一些类,就应该只有一个对象,不应该有多个。

线程池就是这样的,创建两个线程池也没有意义,可以多创建几个线程。

实现方法

将类的构造函数进行私有,这样就无法在创建对象了。

在类中提供一个共有的静态方法,这个方法可以初始化和获取线程池。

4.日志系统

这个没什么难度,就是字符串的拼接,可能需要注意的就是可变参数的使用。

log.hpp

  1. #ifndef __LOG_HPP__
  2. #define __LOG_HPP__
  3. #include <iostream>
  4. #include <string>
  5. #include <time.h>
  6. #include <pthread.h>
  7. #include <sys/types.h>
  8. #include <unistd.h>
  9. #include <stdarg.h>
  10. #include <fstream>
  11. // 日志等级
  12. enum loglevel
  13. {
  14. Debug = 0,
  15. Info,
  16. Warning,
  17. Error,
  18. FATAL,
  19. };
  20. namespace lg
  21. {
  22. bool isSave = false; //是否保存到文件
  23. std::string savefile = "log.txt";//保存的文件名
  24. std::string LeveltoString(int level) //将日志等级转化为字符串
  25. {
  26. switch (level)
  27. {
  28. case Debug:
  29. return "Debug";
  30. case Info:
  31. return "Info";
  32. case Warning:
  33. return "Warning";
  34. case Error:
  35. return "Error";
  36. case FATAL:
  37. return "FATAL";
  38. default:
  39. return "Unknown";
  40. }
  41. }
  42. std::string TimetoString() //将时间转化为字符串
  43. {
  44. time_t cur_time = time(nullptr);
  45. tm *formattime = localtime(&cur_time);
  46. return std::string(std::to_string(formattime->tm_year + 1900) + "/" + std::to_string(formattime->tm_mon + 1) + "/" + std::to_string(formattime->tm_mday) + " " + std::to_string(formattime->tm_hour + 1) + ":" + std::to_string(formattime->tm_min + 1));
  47. }
  48. std::string PidtoString()//将pid转化为字符串
  49. {
  50. return std::to_string(getpid());
  51. }
  52. void SavetoFile(std::string &message)//保存到文件
  53. {
  54. std::ofstream out(savefile, std::ios::app);
  55. if (!out.is_open())
  56. {
  57. return;
  58. }
  59. out << message << std::endl;
  60. out.close();
  61. }
  62. pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  63. // 日志的格式: 日志等级 + 日志时间 + 代码文件名 + 行数 + 日志内容
  64. void LogMessage(std::string filename, int linenum, int level, const char *formate, ...)
  65. {
  66. std::string levelstring = LeveltoString(level);
  67. std::string timestring = TimetoString();
  68. std::string pidstring = PidtoString();
  69. //是对可变参数的解析
  70. char buffer[1024];
  71. va_list ap;
  72. va_start(ap, formate);
  73. vsnprintf(buffer, sizeof(buffer), formate, ap);
  74. va_end(ap);
  75. std::string contentstring = move(std::string(buffer));
  76. std::string message = "[" + levelstring + "]" + "[" + timestring + "]" + "[" + filename + "]" + "[" + std::to_string(linenum) + "]" + "[" + pidstring + "]" + "[" + contentstring + "]";
  77. if (!isSave)
  78. {
  79. pthread_mutex_lock(&mutex);
  80. std::cout << message << std::endl;
  81. pthread_mutex_unlock(&mutex);
  82. }
  83. else
  84. {
  85. SavetoFile(message);
  86. }
  87. }
  88. #define Log(level, format, ...) \
  89. do \
  90. { \
  91. LogMessage(__FILE__, __LINE__, level, format, ##__VA_ARGS__); \
  92. } while (0)
  93. #define save() \
  94. do \
  95. { \
  96. isSave = true; \
  97. } while (0);
  98. #define print() \
  99. do \
  100. { \
  101. isSave = false; \
  102. } while (0);
  103. }
  104. #endif

5.线程池

threadpool.hpp

  1. #ifndef __THREADPOOL__
  2. #define __THREADPOOL__
  3. #include <iostream>
  4. #include <pthread.h>
  5. #include <thread>
  6. #include <unistd.h>
  7. #include <queue>
  8. #include <semaphore.h>
  9. #include "log.hpp"
  10. #include <functional>
  11. // 创建出一批线程,从任务队列里拿任务
  12. namespace mtp
  13. {
  14. using namespace lg;
  15. using namespace std::placeholders;
  16. int _default = 3;
  17. template <class T>
  18. class threadpool
  19. {
  20. private:
  21. threadpool(int threadnum = _default)
  22. : _threadnum(threadnum)
  23. {
  24. pthread_mutex_init(&_mutex, nullptr);
  25. pthread_cond_init(&_cond, nullptr);
  26. Log(Info, "Construct threadpool");
  27. }
  28. // 线程的回调方法
  29. void handlertask(std::string name)
  30. {
  31. while (true)
  32. {
  33. pthread_mutex_lock(&_mutex);
  34. // 线程池运行 任务队列为空时
  35. while (_isrunning && _taskqueue.empty())
  36. {
  37. _waitnum++;
  38. pthread_cond_wait(&_cond, &_mutex);
  39. _waitnum--;
  40. }
  41. // 线程池不运行 任务队列为空
  42. if (!_isrunning && _taskqueue.empty())
  43. {
  44. pthread_mutex_unlock(&_mutex);
  45. break;
  46. }
  47. // 线程池运行 队列不为空
  48. // 线程池不运行 队列不为空
  49. T t = _taskqueue.front();
  50. _taskqueue.pop();
  51. pthread_mutex_unlock(&_mutex);
  52. t(name); // 执行任务
  53. // std::cout<<"handler" << t <<std::endl;
  54. }
  55. }
  56. // 创建线程
  57. void Init()
  58. {
  59. for (int i = 0; i < _threadnum; i++)
  60. {
  61. std::string name = "thread" + std::to_string(i);
  62. _threads.emplace_back(std::bind(&threadpool::handlertask, this, _1), name);
  63. Log(Info, "create %s", name.c_str());
  64. }
  65. }
  66. ~threadpool()
  67. {
  68. pthread_mutex_destroy(&_mutex);
  69. pthread_cond_destroy(&_cond);
  70. Log(Info, "threadpool destory");
  71. }
  72. // 禁止拷贝
  73. threadpool<T> &operator=(const threadpool<T> &) = delete;
  74. threadpool(const threadpool<T> &) = delete;
  75. public:
  76. // 执行单例模式
  77. static threadpool<T>* getInstance()
  78. {
  79. if (_instance == nullptr)//加上这个if语句,如果是获取线程池,就不用获取锁了
  80. {
  81. // 初始化线程池
  82. pthread_mutex_lock(&_lock);
  83. //只有第一次线程创建时才会进,无论创建还是获取都要返回 一个线程池的指针
  84. if (_instance == nullptr)
  85. {
  86. _instance = new threadpool<T>;
  87. _instance->Init();
  88. Log(Info, "Init threadpool");
  89. }
  90. pthread_mutex_unlock(&_lock);
  91. }
  92. Log(Info, "get threadpool");
  93. return _instance;
  94. }
  95. void stop()
  96. {
  97. pthread_mutex_lock(&_mutex);
  98. _isrunning = false;
  99. pthread_mutex_unlock(&_mutex);
  100. pthread_cond_broadcast(&_cond);
  101. }
  102. void waitall()
  103. {
  104. for (auto &thread : _threads)
  105. {
  106. thread.join();
  107. }
  108. Log(Info, "Wait Sucess");
  109. }
  110. void enqueue(T t)
  111. {
  112. pthread_mutex_lock(&_mutex);
  113. if (_isrunning)
  114. {
  115. _taskqueue.push(t);
  116. Log(Info, "push task sucess");
  117. if (_waitnum > 0)
  118. {
  119. pthread_cond_signal(&_cond);
  120. }
  121. }
  122. pthread_mutex_unlock(&_mutex);
  123. }
  124. private:
  125. int _threadnum;
  126. std::vector<std::thread> _threads;
  127. std::queue<T> _taskqueue; // 任务队列
  128. pthread_mutex_t _mutex;
  129. pthread_cond_t _cond;
  130. bool _isrunning = true; // 是否运行
  131. int _waitnum = 0; // d等待的线程数
  132. // 添加单例模式
  133. static threadpool<T> *_instance;
  134. static pthread_mutex_t _lock; // 为了保证单例模式的线程安全
  135. };
  136. template <class T>
  137. threadpool<T> *threadpool<T>::_instance = nullptr;
  138. template <class T>
  139. pthread_mutex_t threadpool<T>::_lock = PTHREAD_MUTEX_INITIALIZER;
  140. }
  141. #endif

Task.hpp

  1. #ifndef __task_HPP__
  2. #define __task_HPP__
  3. #include<string>
  4. #include<stdlib.h>
  5. #include<time.h>
  6. #include<iostream>
  7. class Task
  8. {
  9. public:
  10. Task(std::string taskname)
  11. :_taskname(taskname)
  12. {}
  13. void operator()(std::string name)
  14. {
  15. sleep(1);
  16. std::cout << name <<"Excute "<< _taskname << std::endl;
  17. }
  18. private:
  19. std::string _taskname;
  20. };
  21. #endif

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/运维做开发/article/detail/849148
推荐阅读
相关标签
  

闽ICP备14008679号