线程池:线程池的实现 | 日志

news/2024/10/5 5:05:36/
cle class="baidu_pl">
cle_content" class="article_content clearfix">
content_views" class="markdown_views prism-tomorrow-night">cap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">

c="https://i-blog.csdnimg.cn/direct/5cdb1ad17e8c45e3b976d61052f514f0.png#pic_center" alt="在这里插入图片描述" width="200" />
color="black" face="楷体" size="3">

<center>🌈个人主页: 南桥几晴秋
🌈C++专栏: 南桥谈C++
🌈C语言专栏: C语言学习系列
🌈Linux学习专栏: 南桥谈Linux
🌈数据结构学习专栏: 数据结构杂谈
🌈数据库学习专栏: 南桥谈MySQL
🌈Qt学习专栏: 南桥谈Qt
🌈菜鸡代码练习: 练习随想记录
🌈git学习: 南桥谈Git center>

<center>🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈 <center>本科在读菜鸡一枚࿰c;指出问题及时改正 center> center>

class="toc">

文章目录

  • 原理
  • 线程池实现
  • 日志
    • 获取当前时间函数接口
    • 启用类型设置
    • 输出到屏幕
    • 输出到文件
    • 选择输出方式
    • 创建日志消息
    • 完整代码
  • 携带日志的线程池设计

原理

在一个可执行程序内部存在多个线程和一个任务队列。如果任务队列里长时间没有任务࿰c;这些线程就会休眠࿰c;如果此时来了一个任务࿰c;那么线程就会被唤醒。像这种࿰c;提前创建好线程࿰c;需要的时候直接使用࿰c;我们称之为线程池。这种本质上就是一个生产消费模型。
c="https://i-blog.csdnimg.cn/direct/926ef9f88edb40a19a4098148530c712.png" alt="在这里插入图片描述" />

线程池实现

<code class="prism language-cpp">class="token comment">//ThreadPool.hpp
class="token macro property">class="token directive-hash">#class="token directive keyword">pragma class="token expression">onceclass="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><iostream>
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><unistd.h>
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><string>
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><vector>
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><queue>
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><functional>
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string">"Thread.hpp"class="token keyword">using class="token keyword">namespace threadModelclass="token punctuation">;class="token keyword">static class="token keyword">const class="token keyword">int gdefaultnumclass="token operator">=class="token number">5class="token punctuation">;class="token keyword">void class="token function">testclass="token punctuation">(class="token punctuation">)
class="token punctuation">{class="token keyword">whileclass="token punctuation">(class="token boolean">trueclass="token punctuation">)class="token punctuation">{stdclass="token operator">::coutclass="token operator"><<class="token string">"hello world"class="token operator"><<stdclass="token operator">::endlclass="token punctuation">;class="token function">sleepclass="token punctuation">(class="token number">1class="token punctuation">)class="token punctuation">;class="token punctuation">}
class="token punctuation">}class="token keyword">templateclass="token operator"><class="token keyword">typename class="token class-name">Tclass="token operator">>
class="token keyword">class class="token class-name">ThreadPool
class="token punctuation">{
class="token keyword">privateclass="token operator">:class="token keyword">void class="token function">LockQueueclass="token punctuation">(class="token punctuation">)class="token punctuation">{class="token function">pthread_mutex_lockclass="token punctuation">(class="token operator">&_mutexclass="token punctuation">)class="token punctuation">;class="token punctuation">}class="token keyword">void class="token function">UnlockQueueclass="token punctuation">(class="token punctuation">)class="token punctuation">{class="token function">pthread_mutex_unlockclass="token punctuation">(class="token operator">&_mutexclass="token punctuation">)class="token punctuation">;class="token punctuation">}class="token keyword">void class="token function">Wakeupclass="token punctuation">(class="token punctuation">)class="token punctuation">{class="token function">pthread_cond_signalclass="token punctuation">(class="token operator">&_condclass="token punctuation">)class="token punctuation">;class="token punctuation">}class="token keyword">void class="token function">WakeupAllclass="token punctuation">(class="token punctuation">)class="token punctuation">{class="token function">pthread_cond_broadcastclass="token punctuation">(class="token operator">&_condclass="token punctuation">)class="token punctuation">;class="token punctuation">}class="token keyword">void class="token function">Sleepclass="token punctuation">(class="token punctuation">)class="token punctuation">{class="token function">pthread_cond_waitclass="token punctuation">(class="token operator">&_condclass="token punctuation">,class="token operator">&_mutexclass="token punctuation">)class="token punctuation">;class="token punctuation">}class="token keyword">bool class="token function">IsEmptyclass="token punctuation">(class="token punctuation">)class="token punctuation">{class="token keyword">return _task_queueclass="token punctuation">.class="token function">emptyclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token punctuation">}class="token keyword">void class="token function">HandlerTaskclass="token punctuation">(class="token keyword">const stdclass="token operator">::stringclass="token operator">& nameclass="token punctuation">)  class="token comment">// thisclass="token punctuation">{class="token keyword">while class="token punctuation">(class="token boolean">trueclass="token punctuation">)class="token punctuation">{class="token function">LockQueueclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token comment">//如果队列为空(有任务)class="token keyword">whileclass="token punctuation">(class="token function">IsEmptyclass="token punctuation">(class="token punctuation">)class="token operator">&&_isrunningclass="token punctuation">) class="token comment">//线程没有任务࿰c;但是在工作࿰c;继续休眠class="token punctuation">{_sleep_thread_numclass="token operator">++class="token punctuation">;class="token function">Sleepclass="token punctuation">(class="token punctuation">)class="token punctuation">;_sleep_thread_numclass="token operator">--class="token punctuation">;class="token punctuation">}class="token keyword">ifclass="token punctuation">(class="token function">IsEmptyclass="token punctuation">(class="token punctuation">)class="token operator">&&class="token operator">!_isrunningclass="token punctuation">) class="token comment">// 任务是空的࿰c;并且线程退出工作class="token punctuation">{stdclass="token operator">::coutclass="token operator"><<nameclass="token operator"><<class="token string">" quit..."class="token operator"><<stdclass="token operator">::endlclass="token punctuation">;class="token function">UnlockQueueclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token keyword">breakclass="token punctuation">;class="token punctuation">}class="token comment">// 队列不为空࿰c;有任务 或者 队列被唤醒class="token comment">// 取任务T tclass="token operator">=_task_queueclass="token punctuation">.class="token function">frontclass="token punctuation">(class="token punctuation">)class="token punctuation">;_task_queueclass="token punctuation">.class="token function">popclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token function">UnlockQueueclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token comment">// 此处任务已经不在任务队列中࿰c;任务已经被拿走࿰c;处理任务和临界资源是两码事class="token function">tclass="token punctuation">(class="token punctuation">)class="token punctuation">; class="token comment">// 处理任务࿰c;不能不用也不能在临界区中处理stdclass="token operator">::coutclass="token operator"><<nameclass="token operator"><<class="token string">": "class="token operator"><<tclass="token punctuation">.class="token function">resultclass="token punctuation">(class="token punctuation">)class="token operator"><<stdclass="token operator">::endlclass="token punctuation">;class="token punctuation">}class="token punctuation">}class="token keyword">publicclass="token operator">:class="token function">ThreadPoolclass="token punctuation">(class="token keyword">int thread_numclass="token operator">=gdefaultnumclass="token punctuation">)class="token operator">:class="token function">_thread_numclass="token punctuation">(thread_numclass="token punctuation">)class="token punctuation">,class="token function">_isrunningclass="token punctuation">(class="token boolean">falseclass="token punctuation">) class="token comment">//刚开始线程没有使用class="token punctuation">,class="token function">_sleep_thread_numclass="token punctuation">(class="token number">0class="token punctuation">)class="token punctuation">{class="token function">pthread_mutex_initclass="token punctuation">(class="token operator">&_mutexclass="token punctuation">,class="token keyword">nullptrclass="token punctuation">)class="token punctuation">;class="token function">pthread_cond_initclass="token punctuation">(class="token operator">&_condclass="token punctuation">,class="token keyword">nullptrclass="token punctuation">)class="token punctuation">;class="token punctuation">}class="token keyword">void class="token function">Initclass="token punctuation">(class="token punctuation">)class="token punctuation">{func_t funcclass="token operator">=stdclass="token operator">::class="token function">bindclass="token punctuation">(class="token operator">&ThreadPoolclass="token operator">::HandlerTaskclass="token punctuation">,class="token keyword">thisclass="token punctuation">,stdclass="token operator">::placeholdersclass="token operator">::_1class="token punctuation">)class="token punctuation">;class="token keyword">forclass="token punctuation">(class="token keyword">int iclass="token operator">=class="token number">0class="token punctuation">;iclass="token operator"><_thread_numclass="token punctuation">;iclass="token operator">++class="token punctuation">)class="token punctuation">{stdclass="token operator">::string threadnameclass="token operator">=class="token string">"thread-"class="token operator">+stdclass="token operator">::class="token function">to_stringclass="token punctuation">(iclass="token operator">+class="token number">1class="token punctuation">)class="token punctuation">;_threadsclass="token punctuation">.class="token function">emplace_backclass="token punctuation">(threadnameclass="token punctuation">,funcclass="token punctuation">)class="token punctuation">;class="token punctuation">}class="token punctuation">}class="token keyword">void class="token function">Startclass="token punctuation">(class="token punctuation">)class="token punctuation">{_isrunningclass="token operator">=class="token boolean">trueclass="token punctuation">;class="token keyword">forclass="token punctuation">(class="token keyword">autoclass="token operator">& threadclass="token operator">:_threadsclass="token punctuation">)class="token punctuation">{threadclass="token punctuation">.class="token function">Startclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token punctuation">}class="token punctuation">}class="token keyword">void class="token function">Stopclass="token punctuation">(class="token punctuation">)class="token punctuation">{class="token function">LockQueueclass="token punctuation">(class="token punctuation">)class="token punctuation">;_isrunningclass="token operator">=class="token boolean">falseclass="token punctuation">;class="token function">WakeupAllclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token function">UnlockQueueclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token punctuation">}class="token keyword">void class="token function">Equeueclass="token punctuation">(class="token keyword">const T class="token operator">&inclass="token punctuation">)class="token punctuation">{class="token function">LockQueueclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token keyword">ifclass="token punctuation">(_isrunningclass="token punctuation">)class="token punctuation">{_task_queueclass="token punctuation">.class="token function">pushclass="token punctuation">(inclass="token punctuation">)class="token punctuation">;class="token comment">// 如果当前有线程在等待࿰c;需要唤醒class="token keyword">ifclass="token punctuation">(_sleep_thread_numclass="token operator">>class="token number">0class="token punctuation">)class="token punctuation">{class="token function">Wakeupclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token punctuation">}class="token punctuation">}class="token function">UnlockQueueclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token punctuation">}class="token operator">~class="token function">ThreadPoolclass="token punctuation">(class="token punctuation">)class="token punctuation">{class="token function">pthread_mutex_destroyclass="token punctuation">(class="token operator">&_mutexclass="token punctuation">)class="token punctuation">;class="token function">pthread_cond_destroyclass="token punctuation">(class="token operator">&_condclass="token punctuation">)class="token punctuation">;class="token punctuation">}
class="token keyword">privateclass="token operator">:class="token keyword">int _thread_numclass="token punctuation">;stdclass="token operator">::vectorclass="token operator"><Threadclass="token operator">> _threadsclass="token punctuation">;  class="token comment">// 管理多个线程stdclass="token operator">::queueclass="token operator"><Tclass="token operator">> _task_queueclass="token punctuation">; class="token comment">// 任务队列class="token keyword">bool _isrunningclass="token punctuation">; class="token comment">//当前线程是否在工作class="token keyword">int _sleep_thread_numclass="token punctuation">;   class="token comment">//计数器:休眠的线程个数pthread_mutex_t _mutexclass="token punctuation">;pthread_cond_t _condclass="token punctuation">;
class="token punctuation">}class="token punctuation">;code>

c="https://i-blog.csdnimg.cn/direct/e5baae6072804dff8d17b2075a7fccd2.gif#pic_center" alt="在这里插入图片描述" />

日志

日志是软件运行的记录信息࿰c;可以向显示器打印࿰c;也可以向文件中打印࿰c;日志必须有特定的格式:

  • [日志等级] [pid] [filename] [filenumber] [time] 日志内容(支持可变参数)

日志等级:DEBUG、INFO、WARNING、ERROR、FATAL(致命的)

<code class="prism language-cpp">class="token comment">// 日志等级
class="token keyword">enum
class="token punctuation">{DEBUGclass="token operator">=class="token number">1class="token punctuation">,INFOclass="token punctuation">,WARINGclass="token punctuation">,ERRORclass="token punctuation">,FATAL
class="token punctuation">}class="token punctuation">;
code>
  • 日志消息:日志等级、id、文件名、行号、当前时间等
<code class="prism language-cpp">class="token comment">// 日志消息
class="token keyword">class class="token class-name">logmessage
class="token punctuation">{class="token keyword">publicclass="token operator">:stdclass="token operator">::string _levelclass="token punctuation">; class="token comment">// 日志等级pid_t _idclass="token punctuation">; stdclass="token operator">::string _filenameclass="token punctuation">; class="token comment">// 文件名class="token keyword">int _filenumberclass="token punctuation">;  class="token comment">// 行号stdclass="token operator">::string _cur_timeclass="token punctuation">;stdclass="token operator">::string _message_infoclass="token punctuation">;class="token punctuation">}class="token punctuation">;
code>

获取当前时间函数接口

<code class="prism language-cpp">stdclass="token operator">::string class="token function">GetCurTimeclass="token punctuation">(class="token punctuation">)
class="token punctuation">{time_t nowclass="token operator">=class="token function">timeclass="token punctuation">(class="token keyword">nullptrclass="token punctuation">)class="token punctuation">;class="token keyword">struct class="token class-name">tmclass="token operator">* cur_timeclass="token operator">=class="token function">localtimeclass="token punctuation">(class="token operator">&nowclass="token punctuation">)class="token punctuation">;class="token keyword">char bufferclass="token punctuation">[class="token number">128class="token punctuation">]class="token punctuation">;class="token function">snprintfclass="token punctuation">(bufferclass="token punctuation">,class="token keyword">sizeofclass="token punctuation">(bufferclass="token punctuation">)class="token punctuation">,class="token string">"%d-%02d-%02d %02d:%02d:%02d"class="token punctuation">,cur_timeclass="token operator">->tm_yearclass="token operator">+class="token number">1900class="token punctuation">,cur_timeclass="token operator">->tm_monclass="token operator">+class="token number">1class="token punctuation">,cur_timeclass="token operator">->tm_mdayclass="token punctuation">,cur_timeclass="token operator">->tm_hourclass="token punctuation">,cur_timeclass="token operator">->tm_minclass="token punctuation">,cur_timeclass="token operator">->tm_secclass="token punctuation">)class="token punctuation">;class="token keyword">return stdclass="token operator">::class="token function">stringclass="token punctuation">(bufferclass="token punctuation">)class="token punctuation">;
class="token punctuation">}
code>
  • <code>time(nullptr) code>返回当前的时间(从 1970 年 1 月 1 日到现在的秒数)࿰c;并将其赋值给 <code>nowcode> 变量。<code>time_tcode> 是表示时间点的类型。
  • <code>localtime(&now) code>将 <code>now code>转换为当地时间࿰c;并返回一个指向<code> tmcode> 结构的指针。<code>tmcode> 结构包含了年、月、日、时、分、秒等信息。
    c="https://i-blog.csdnimg.cn/direct/3c5dcc072c7746c6b6ca780a27cd4bf5.png" alt="在这里插入图片描述" />

启用类型设置

<code class="prism language-cpp">class="token keyword">void class="token function">Enableclass="token punctuation">(class="token keyword">int typeclass="token punctuation">)
class="token punctuation">{_typeclass="token operator">=typeclass="token punctuation">;
class="token punctuation">}code>

<code>Enablecode> 函数用于设置日志输出类型࿰c;可以选择输出到屏幕或文件。

输出到屏幕

<code class="prism language-cpp">class="token keyword">void class="token function">FlushLogToSCreenclass="token punctuation">(class="token keyword">const logmessageclass="token operator">& lgclass="token punctuation">)
class="token punctuation">{class="token function">printfclass="token punctuation">(class="token string">"[%s][%d][%s][%d][%s] %s"class="token punctuation">,lgclass="token punctuation">._levelclass="token punctuation">.class="token function">c_strclass="token punctuation">(class="token punctuation">)class="token punctuation">,lgclass="token punctuation">._idclass="token punctuation">,lgclass="token punctuation">._filenameclass="token punctuation">.class="token function">c_strclass="token punctuation">(class="token punctuation">)class="token punctuation">,lgclass="token punctuation">._filenumberclass="token punctuation">,lgclass="token punctuation">._cur_timeclass="token punctuation">.class="token function">c_strclass="token punctuation">(class="token punctuation">)class="token punctuation">,lgclass="token punctuation">._message_infoclass="token punctuation">.class="token function">c_strclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">;
class="token punctuation">}code>

<code>FlushLogToSCreen code>函数将日志信息格式化并输出到控制台。使用 <code>printfcode> 格式化字符串。

输出到文件

<code class="prism language-cpp">class="token keyword">void class="token function">FlushLogToFileclass="token punctuation">(class="token keyword">const logmessageclass="token operator">& lgclass="token punctuation">)
class="token punctuation">{stdclass="token operator">::ofstream class="token function">outclass="token punctuation">(_logfileclass="token punctuation">,stdclass="token operator">::iosclass="token operator">::appclass="token punctuation">)class="token punctuation">; class="token comment">// 追加打印class="token keyword">ifclass="token punctuation">(class="token operator">!outclass="token punctuation">.class="token function">is_openclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token keyword">returnclass="token punctuation">;class="token keyword">char logtxtclass="token punctuation">[class="token number">2048class="token punctuation">]class="token punctuation">;class="token function">snprintfclass="token punctuation">(logtxtclass="token punctuation">,class="token keyword">sizeofclass="token punctuation">(logtxtclass="token punctuation">)class="token punctuation">,class="token string">"[%s][%d][%s][%d][%s] %s"class="token punctuation">,lgclass="token punctuation">._levelclass="token punctuation">.class="token function">c_strclass="token punctuation">(class="token punctuation">)class="token punctuation">,lgclass="token punctuation">._idclass="token punctuation">,lgclass="token punctuation">._filenameclass="token punctuation">.class="token function">c_strclass="token punctuation">(class="token punctuation">)class="token punctuation">,lgclass="token punctuation">._filenumberclass="token punctuation">,lgclass="token punctuation">._cur_timeclass="token punctuation">.class="token function">c_strclass="token punctuation">(class="token punctuation">)class="token punctuation">,lgclass="token punctuation">._message_infoclass="token punctuation">.class="token function">c_strclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">;outclass="token punctuation">.class="token function">writeclass="token punctuation">(logtxtclass="token punctuation">,class="token function">strlenclass="token punctuation">(logtxtclass="token punctuation">)class="token punctuation">)class="token punctuation">;outclass="token punctuation">.class="token function">closeclass="token punctuation">(class="token punctuation">)class="token punctuation">;
class="token punctuation">}code>

<code>FlushLogToFile code>函数将日志信息写入指定的文件。以追加模式打开文件࿰c;并在打开失败时返回。
使用<code>snprintf code>格式化日志信息࿰c;然后将其写入文件。

选择输出方式

<code class="prism language-cpp">class="token keyword">void class="token function">FlushLogclass="token punctuation">(class="token keyword">const logmessageclass="token operator">& lgclass="token punctuation">)
class="token punctuation">{class="token keyword">switchclass="token punctuation">(_typeclass="token punctuation">)class="token punctuation">{class="token keyword">case SCREEN_TYPEclass="token operator">:class="token function">FlushLogToSCreenclass="token punctuation">(lgclass="token punctuation">)class="token punctuation">;class="token keyword">breakclass="token punctuation">;class="token keyword">case FILE_TYPEclass="token operator">:class="token function">FlushLogToFileclass="token punctuation">(lgclass="token punctuation">)class="token punctuation">;class="token keyword">breakclass="token punctuation">;class="token punctuation">}
class="token punctuation">}code>

创建日志消息

<code class="prism language-cpp">class="token keyword">void class="token function">logMessageclass="token punctuation">(stdclass="token operator">::string filenameclass="token punctuation">,class="token keyword">int filenumberclass="token punctuation">,class="token keyword">int levelclass="token punctuation">,class="token keyword">const class="token keyword">charclass="token operator">* formatclass="token punctuation">,class="token punctuation">.class="token punctuation">.class="token punctuation">.class="token punctuation">)
class="token punctuation">{logmessage lgclass="token punctuation">;lgclass="token punctuation">._levelclass="token operator">=class="token function">LevelToStringclass="token punctuation">(levelclass="token punctuation">)class="token punctuation">;lgclass="token punctuation">._idclass="token operator">=class="token function">getpidclass="token punctuation">(class="token punctuation">)class="token punctuation">;lgclass="token punctuation">._filenameclass="token operator">=filenameclass="token punctuation">;lgclass="token punctuation">._filenumberclass="token operator">=filenumberclass="token punctuation">;lgclass="token punctuation">._cur_timeclass="token operator">=class="token function">GetCurTimeclass="token punctuation">(class="token punctuation">)class="token punctuation">;va_list apclass="token punctuation">;class="token function">va_startclass="token punctuation">(apclass="token punctuation">,formatclass="token punctuation">)class="token punctuation">;class="token keyword">char log_infoclass="token punctuation">[class="token number">1024class="token punctuation">]class="token punctuation">;class="token function">vsnprintfclass="token punctuation">(log_infoclass="token punctuation">,class="token keyword">sizeofclass="token punctuation">(log_infoclass="token punctuation">)class="token punctuation">,formatclass="token punctuation">,apclass="token punctuation">)class="token punctuation">;class="token function">va_endclass="token punctuation">(apclass="token punctuation">)class="token punctuation">;lgclass="token punctuation">._message_infoclass="token operator">=log_infoclass="token punctuation">;class="token function">FlushLogclass="token punctuation">(lgclass="token punctuation">)class="token punctuation">;
class="token punctuation">}code>
  • <code>logMessagecode> 函数用于创建一条新的日志消息。它接受文件名、文件编号、日志级别和格式化字符串作为参数。
  • 使用可变参数处理(<code>va_listcode>)来处理格式化字符串。
  • 将生成的日志信息存储在 <code>lgcode> 对象中࿰c;并调用 <code>FlushLogcode> 函数进行输出。
  • <code>va_list ap;code>声明了一个 <code>va_listcode> 类型的变量 <code>apcode>࿰c;它用于存储可变参数列表。在 C 语言中࿰c;<code>va_listcode> 是一个用于遍历不定数量参数的类型。
  • <code>va_start(ap, format);code>:<code>va_startcode> 宏初始化 <code>apcode> 以指向函数参数列表中的第一个可变参数。这里的 <code>formatcode> 是最后一个固定参数࿰c;<code>va_startcode> 会从它的下一个参数开始读取可变参数。因此࿰c;<code>apcode> 现在可以用来访问 <code>formatcode> 之后的所有参数。
  • <code>va_end(ap)code>用于清理<code>va_listcode> 变量 <code>apcode>。在读取完可变参数后࿰c;调用 <code>va_end code>是良好的实践࿰c;它可以释放与 <code>apcode> 相关的资源(如果有的话)。

完整代码

<code class="prism language-cpp">class="token macro property">class="token directive-hash">#class="token directive keyword">pragma class="token expression">onceclass="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><iostream>
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><string>
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><cstring>
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><sys/types.h>
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><unistd.h>
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><stdarg.h>
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><ctime>
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><fstream>
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><pthread.h>
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><cstdio>
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string">"LockGuard.hpp"class="token keyword">using stdclass="token operator">::cinclass="token punctuation">;
class="token keyword">using stdclass="token operator">::coutclass="token punctuation">;
class="token keyword">using stdclass="token operator">::endlclass="token punctuation">;class="token keyword">namespace log_ns
class="token punctuation">{class="token comment">// 日志等级class="token keyword">enumclass="token punctuation">{DEBUGclass="token operator">=class="token number">1class="token punctuation">,INFOclass="token punctuation">,WARINGclass="token punctuation">,ERRORclass="token punctuation">,FATALclass="token punctuation">}class="token punctuation">;class="token comment">// 日志消息class="token keyword">class class="token class-name">logmessageclass="token punctuation">{class="token keyword">publicclass="token operator">:stdclass="token operator">::string _levelclass="token punctuation">; class="token comment">// 日志等级pid_t _idclass="token punctuation">; stdclass="token operator">::string _filenameclass="token punctuation">; class="token comment">// 文件名class="token keyword">int _filenumberclass="token punctuation">;  class="token comment">// 行号stdclass="token operator">::string _cur_timeclass="token punctuation">;stdclass="token operator">::string _message_infoclass="token punctuation">;class="token punctuation">}class="token punctuation">;pthread_mutex_t glockclass="token operator">=PTHREAD_MUTEX_INITIALIZERclass="token punctuation">; class="token comment">// 定义一个全局的锁stdclass="token operator">::string class="token function">LevelToStringclass="token punctuation">(class="token keyword">int levelclass="token punctuation">)class="token punctuation">{LockGuard class="token function">lockguardclass="token punctuation">(class="token operator">&glockclass="token punctuation">)class="token punctuation">;class="token keyword">switchclass="token punctuation">(levelclass="token punctuation">)class="token punctuation">{class="token keyword">case DEBUGclass="token operator">:class="token keyword">return class="token string">"DEBUG"class="token punctuation">;class="token keyword">case INFOclass="token operator">:class="token keyword">return class="token string">"INFO"class="token punctuation">;class="token keyword">case WARINGclass="token operator">:class="token keyword">return class="token string">"WARING"class="token punctuation">;class="token keyword">case ERRORclass="token operator">:class="token keyword">return class="token string">"ERROR"class="token punctuation">;class="token keyword">case FATALclass="token operator">:class="token keyword">return class="token string">"FATAL"class="token punctuation">;class="token keyword">defaultclass="token operator">:class="token keyword">return class="token string">"UNKNOWN"class="token punctuation">;class="token punctuation">}class="token punctuation">}stdclass="token operator">::string class="token function">GetCurTimeclass="token punctuation">(class="token punctuation">)class="token punctuation">{time_t nowclass="token operator">=class="token function">timeclass="token punctuation">(class="token keyword">nullptrclass="token punctuation">)class="token punctuation">;class="token keyword">struct class="token class-name">tmclass="token operator">* cur_timeclass="token operator">=class="token function">localtimeclass="token punctuation">(class="token operator">&nowclass="token punctuation">)class="token punctuation">;class="token keyword">char bufferclass="token punctuation">[class="token number">128class="token punctuation">]class="token punctuation">;class="token function">snprintfclass="token punctuation">(bufferclass="token punctuation">,class="token keyword">sizeofclass="token punctuation">(bufferclass="token punctuation">)class="token punctuation">,class="token string">"%d-%02d-%02d %02d:%02d:%02d"class="token punctuation">,cur_timeclass="token operator">->tm_yearclass="token operator">+class="token number">1900class="token punctuation">,cur_timeclass="token operator">->tm_monclass="token operator">+class="token number">1class="token punctuation">,cur_timeclass="token operator">->tm_mdayclass="token punctuation">,cur_timeclass="token operator">->tm_hourclass="token punctuation">,cur_timeclass="token operator">->tm_minclass="token punctuation">,cur_timeclass="token operator">->tm_secclass="token punctuation">)class="token punctuation">;class="token keyword">return stdclass="token operator">::class="token function">stringclass="token punctuation">(bufferclass="token punctuation">)class="token punctuation">;class="token punctuation">}class="token macro property">class="token directive-hash">#class="token directive keyword">define class="token macro-name">SCREEN_TYPE class="token expression">class="token number">1class="token macro property">class="token directive-hash">#class="token directive keyword">define class="token macro-name">FILE_TYPE class="token expression">class="token number">2class="token keyword">const stdclass="token operator">::string glogfileclass="token operator">=class="token string">"./log.txt"class="token punctuation">;class="token comment">// 日志class="token keyword">class class="token class-name">Logclass="token punctuation">{class="token keyword">publicclass="token operator">:class="token function">Logclass="token punctuation">(class="token keyword">const stdclass="token operator">::stringclass="token operator">& logfeileclass="token operator">=glogfileclass="token punctuation">)class="token operator">:class="token function">_logfileclass="token punctuation">(logfeileclass="token punctuation">)class="token punctuation">,class="token function">_typeclass="token punctuation">(SCREEN_TYPEclass="token punctuation">)class="token punctuation">{class="token punctuation">}class="token keyword">void class="token function">Enableclass="token punctuation">(class="token keyword">int typeclass="token punctuation">)class="token punctuation">{_typeclass="token operator">=typeclass="token punctuation">;class="token punctuation">}class="token keyword">void class="token function">FlushLogToSCreenclass="token punctuation">(class="token keyword">const logmessageclass="token operator">& lgclass="token punctuation">)class="token punctuation">{class="token function">printfclass="token punctuation">(class="token string">"[%s][%d][%s][%d][%s] %s"class="token punctuation">,lgclass="token punctuation">._levelclass="token punctuation">.class="token function">c_strclass="token punctuation">(class="token punctuation">)class="token punctuation">,lgclass="token punctuation">._idclass="token punctuation">,lgclass="token punctuation">._filenameclass="token punctuation">.class="token function">c_strclass="token punctuation">(class="token punctuation">)class="token punctuation">,lgclass="token punctuation">._filenumberclass="token punctuation">,lgclass="token punctuation">._cur_timeclass="token punctuation">.class="token function">c_strclass="token punctuation">(class="token punctuation">)class="token punctuation">,lgclass="token punctuation">._message_infoclass="token punctuation">.class="token function">c_strclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">;class="token punctuation">}class="token keyword">void class="token function">FlushLogToFileclass="token punctuation">(class="token keyword">const logmessageclass="token operator">& lgclass="token punctuation">)class="token punctuation">{stdclass="token operator">::ofstream class="token function">outclass="token punctuation">(_logfileclass="token punctuation">,stdclass="token operator">::iosclass="token operator">::appclass="token punctuation">)class="token punctuation">; class="token comment">// 追加打印class="token keyword">ifclass="token punctuation">(class="token operator">!outclass="token punctuation">.class="token function">is_openclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token keyword">returnclass="token punctuation">;class="token keyword">char logtxtclass="token punctuation">[class="token number">2048class="token punctuation">]class="token punctuation">;class="token function">snprintfclass="token punctuation">(logtxtclass="token punctuation">,class="token keyword">sizeofclass="token punctuation">(logtxtclass="token punctuation">)class="token punctuation">,class="token string">"[%s][%d][%s][%d][%s] %s"class="token punctuation">,lgclass="token punctuation">._levelclass="token punctuation">.class="token function">c_strclass="token punctuation">(class="token punctuation">)class="token punctuation">,lgclass="token punctuation">._idclass="token punctuation">,lgclass="token punctuation">._filenameclass="token punctuation">.class="token function">c_strclass="token punctuation">(class="token punctuation">)class="token punctuation">,lgclass="token punctuation">._filenumberclass="token punctuation">,lgclass="token punctuation">._cur_timeclass="token punctuation">.class="token function">c_strclass="token punctuation">(class="token punctuation">)class="token punctuation">,lgclass="token punctuation">._message_infoclass="token punctuation">.class="token function">c_strclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">;outclass="token punctuation">.class="token function">writeclass="token punctuation">(logtxtclass="token punctuation">,class="token function">strlenclass="token punctuation">(logtxtclass="token punctuation">)class="token punctuation">)class="token punctuation">;outclass="token punctuation">.class="token function">closeclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token punctuation">}class="token keyword">void class="token function">FlushLogclass="token punctuation">(class="token keyword">const logmessageclass="token operator">& lgclass="token punctuation">)class="token punctuation">{class="token keyword">switchclass="token punctuation">(_typeclass="token punctuation">)class="token punctuation">{class="token keyword">case SCREEN_TYPEclass="token operator">:class="token function">FlushLogToSCreenclass="token punctuation">(lgclass="token punctuation">)class="token punctuation">;class="token keyword">breakclass="token punctuation">;class="token keyword">case FILE_TYPEclass="token operator">:class="token function">FlushLogToFileclass="token punctuation">(lgclass="token punctuation">)class="token punctuation">;class="token keyword">breakclass="token punctuation">;class="token punctuation">}class="token punctuation">}class="token keyword">void class="token function">logMessageclass="token punctuation">(stdclass="token operator">::string filenameclass="token punctuation">,class="token keyword">int filenumberclass="token punctuation">,class="token keyword">int levelclass="token punctuation">,class="token keyword">const class="token keyword">charclass="token operator">* formatclass="token punctuation">,class="token punctuation">.class="token punctuation">.class="token punctuation">.class="token punctuation">)class="token punctuation">{logmessage lgclass="token punctuation">;lgclass="token punctuation">._levelclass="token operator">=class="token function">LevelToStringclass="token punctuation">(levelclass="token punctuation">)class="token punctuation">;lgclass="token punctuation">._idclass="token operator">=class="token function">getpidclass="token punctuation">(class="token punctuation">)class="token punctuation">;lgclass="token punctuation">._filenameclass="token operator">=filenameclass="token punctuation">;lgclass="token punctuation">._filenumberclass="token operator">=filenumberclass="token punctuation">;lgclass="token punctuation">._cur_timeclass="token operator">=class="token function">GetCurTimeclass="token punctuation">(class="token punctuation">)class="token punctuation">;va_list apclass="token punctuation">;class="token function">va_startclass="token punctuation">(apclass="token punctuation">,formatclass="token punctuation">)class="token punctuation">;class="token keyword">char log_infoclass="token punctuation">[class="token number">1024class="token punctuation">]class="token punctuation">;class="token function">vsnprintfclass="token punctuation">(log_infoclass="token punctuation">,class="token keyword">sizeofclass="token punctuation">(log_infoclass="token punctuation">)class="token punctuation">,formatclass="token punctuation">,apclass="token punctuation">)class="token punctuation">;class="token function">va_endclass="token punctuation">(apclass="token punctuation">)class="token punctuation">;lgclass="token punctuation">._message_infoclass="token operator">=log_infoclass="token punctuation">;class="token comment">//cout<<lg._message_info<<endl;class="token comment">// 打印日志class="token function">FlushLogclass="token punctuation">(lgclass="token punctuation">)class="token punctuation">;class="token punctuation">}class="token operator">~class="token function">Logclass="token punctuation">(class="token punctuation">)class="token punctuation">{class="token punctuation">}class="token keyword">privateclass="token operator">:class="token keyword">int _typeclass="token punctuation">;stdclass="token operator">::string _logfileclass="token punctuation">;class="token punctuation">}class="token punctuation">;Log lgclass="token punctuation">;class="token macro property">class="token directive-hash">#class="token directive keyword">define class="token macro-name function">LOGclass="token expression">class="token punctuation">(Levelclass="token punctuation">,Formatclass="token punctuation">,class="token punctuation">.class="token punctuation">.class="token punctuation">.class="token punctuation">) class="token keyword">doclass="token punctuation">{lgclass="token punctuation">.class="token function">logMessageclass="token punctuation">(class="token constant">__FILE__class="token punctuation">,class="token constant">__LINE__class="token punctuation">,Levelclass="token punctuation">,Formatclass="token punctuation">,class="token punctuation">##class="token expression">__VA_ARGS__class="token punctuation">)class="token punctuation">;class="token punctuation">}class="token keyword">whileclass="token punctuation">(class="token number">0class="token punctuation">)class="token macro property">class="token directive-hash">#class="token directive keyword">define class="token macro-name function">EnableScreenclass="token expression">class="token punctuation">(class="token punctuation">) class="token keyword">doclass="token punctuation">{lgclass="token punctuation">.class="token function">Enableclass="token punctuation">(SCREEN_TYPEclass="token punctuation">)class="token punctuation">;class="token punctuation">}class="token keyword">whileclass="token punctuation">(class="token number">0class="token punctuation">)class="token macro property">class="token directive-hash">#class="token directive keyword">define class="token macro-name function">EnableFileclass="token expression">class="token punctuation">(class="token punctuation">) class="token keyword">doclass="token punctuation">{lgclass="token punctuation">.class="token function">Enableclass="token punctuation">(FILE_TYPEclass="token punctuation">)class="token punctuation">;class="token punctuation">}class="token keyword">whileclass="token punctuation">(class="token number">0class="token punctuation">)class="token punctuation">}class="token punctuation">;
code>

c="https://i-blog.csdnimg.cn/direct/c3030a93cda64a00b51efbfee7619257.png" alt="在这里插入图片描述" />

携带日志的线程池设计

<code class="prism language-cpp">class="token comment">//ThreadPool.hpp
class="token macro property">class="token directive-hash">#class="token directive keyword">pragma class="token expression">onceclass="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><iostream>
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><unistd.h>
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><string>
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><vector>
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><queue>
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><functional>
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string">"Thread.hpp"
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string">"Log.hpp"class="token keyword">using class="token keyword">namespace threadModelclass="token punctuation">;
class="token keyword">using class="token keyword">namespace log_nsclass="token punctuation">;class="token keyword">static class="token keyword">const class="token keyword">int gdefaultnumclass="token operator">=class="token number">5class="token punctuation">;class="token keyword">void class="token function">testclass="token punctuation">(class="token punctuation">)
class="token punctuation">{class="token keyword">whileclass="token punctuation">(class="token boolean">trueclass="token punctuation">)class="token punctuation">{stdclass="token operator">::coutclass="token operator"><<class="token string">"hello world"class="token operator"><<stdclass="token operator">::endlclass="token punctuation">;class="token function">sleepclass="token punctuation">(class="token number">1class="token punctuation">)class="token punctuation">;class="token punctuation">}
class="token punctuation">}class="token keyword">templateclass="token operator"><class="token keyword">typename class="token class-name">Tclass="token operator">>
class="token keyword">class class="token class-name">ThreadPool
class="token punctuation">{
class="token keyword">privateclass="token operator">:class="token keyword">void class="token function">LockQueueclass="token punctuation">(class="token punctuation">)class="token punctuation">{class="token function">pthread_mutex_lockclass="token punctuation">(class="token operator">&_mutexclass="token punctuation">)class="token punctuation">;class="token punctuation">}class="token keyword">void class="token function">UnlockQueueclass="token punctuation">(class="token punctuation">)class="token punctuation">{class="token function">pthread_mutex_unlockclass="token punctuation">(class="token operator">&_mutexclass="token punctuation">)class="token punctuation">;class="token punctuation">}class="token keyword">void class="token function">Wakeupclass="token punctuation">(class="token punctuation">)class="token punctuation">{class="token function">pthread_cond_signalclass="token punctuation">(class="token operator">&_condclass="token punctuation">)class="token punctuation">;class="token punctuation">}class="token keyword">void class="token function">WakeupAllclass="token punctuation">(class="token punctuation">)class="token punctuation">{class="token function">pthread_cond_broadcastclass="token punctuation">(class="token operator">&_condclass="token punctuation">)class="token punctuation">;class="token punctuation">}class="token keyword">void class="token function">Sleepclass="token punctuation">(class="token punctuation">)class="token punctuation">{class="token function">pthread_cond_waitclass="token punctuation">(class="token operator">&_condclass="token punctuation">,class="token operator">&_mutexclass="token punctuation">)class="token punctuation">;class="token punctuation">}class="token keyword">bool class="token function">IsEmptyclass="token punctuation">(class="token punctuation">)class="token punctuation">{class="token keyword">return _task_queueclass="token punctuation">.class="token function">emptyclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token punctuation">}class="token keyword">void class="token function">HandlerTaskclass="token punctuation">(class="token keyword">const stdclass="token operator">::stringclass="token operator">& nameclass="token punctuation">)  class="token comment">// thisclass="token punctuation">{class="token keyword">while class="token punctuation">(class="token boolean">trueclass="token punctuation">)class="token punctuation">{class="token function">LockQueueclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token comment">//如果队列为空(有任务)class="token keyword">whileclass="token punctuation">(class="token function">IsEmptyclass="token punctuation">(class="token punctuation">)class="token operator">&&_isrunningclass="token punctuation">) class="token comment">//线程没有任务࿰c;但是在工作࿰c;继续休眠class="token punctuation">{_sleep_thread_numclass="token operator">++class="token punctuation">;class="token function">LOGclass="token punctuation">(INFOclass="token punctuation">,class="token string">"%s thread sleep begin!\n"class="token punctuation">,nameclass="token punctuation">.class="token function">c_strclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">;class="token function">Sleepclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token function">LOGclass="token punctuation">(INFOclass="token punctuation">,class="token string">"%s thread wakeup!\n"class="token punctuation">,nameclass="token punctuation">.class="token function">c_strclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">;_sleep_thread_numclass="token operator">--class="token punctuation">;class="token punctuation">}class="token keyword">ifclass="token punctuation">(class="token function">IsEmptyclass="token punctuation">(class="token punctuation">)class="token operator">&&class="token operator">!_isrunningclass="token punctuation">) class="token comment">// 任务是空的࿰c;并且线程退出工作class="token punctuation">{class="token function">UnlockQueueclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token function">LOGclass="token punctuation">(INFOclass="token punctuation">,class="token string">"%s quit\n"class="token punctuation">,nameclass="token punctuation">.class="token function">c_strclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">;class="token keyword">breakclass="token punctuation">;class="token punctuation">}class="token comment">// 队列不为空࿰c;有任务 或者 队列被唤醒class="token comment">// 取任务T tclass="token operator">=_task_queueclass="token punctuation">.class="token function">frontclass="token punctuation">(class="token punctuation">)class="token punctuation">;_task_queueclass="token punctuation">.class="token function">popclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token function">UnlockQueueclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token comment">// 此处任务已经不在任务队列中࿰c;任务已经被拿走࿰c;处理任务和临界资源是两码事class="token function">tclass="token punctuation">(class="token punctuation">)class="token punctuation">; class="token comment">// 处理任务࿰c;不能不用也不能在临界区中处理class="token function">LOGclass="token punctuation">(DEBUGclass="token punctuation">,class="token string">"hander task done, task is: \n%s"class="token punctuation">,tclass="token punctuation">.class="token function">resultclass="token punctuation">(class="token punctuation">)class="token punctuation">.class="token function">c_strclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">;class="token punctuation">}class="token punctuation">}class="token keyword">publicclass="token operator">:class="token function">ThreadPoolclass="token punctuation">(class="token keyword">int thread_numclass="token operator">=gdefaultnumclass="token punctuation">)class="token operator">:class="token function">_thread_numclass="token punctuation">(thread_numclass="token punctuation">)class="token punctuation">,class="token function">_isrunningclass="token punctuation">(class="token boolean">falseclass="token punctuation">) class="token comment">//刚开始线程没有使用class="token punctuation">,class="token function">_sleep_thread_numclass="token punctuation">(class="token number">0class="token punctuation">)class="token punctuation">{class="token function">pthread_mutex_initclass="token punctuation">(class="token operator">&_mutexclass="token punctuation">,class="token keyword">nullptrclass="token punctuation">)class="token punctuation">;class="token function">pthread_cond_initclass="token punctuation">(class="token operator">&_condclass="token punctuation">,class="token keyword">nullptrclass="token punctuation">)class="token punctuation">;class="token punctuation">}class="token keyword">void class="token function">Initclass="token punctuation">(class="token punctuation">)class="token punctuation">{func_t funcclass="token operator">=stdclass="token operator">::class="token function">bindclass="token punctuation">(class="token operator">&ThreadPoolclass="token operator">::HandlerTaskclass="token punctuation">,class="token keyword">thisclass="token punctuation">,stdclass="token operator">::placeholdersclass="token operator">::_1class="token punctuation">)class="token punctuation">;class="token keyword">forclass="token punctuation">(class="token keyword">int iclass="token operator">=class="token number">0class="token punctuation">;iclass="token operator"><_thread_numclass="token punctuation">;iclass="token operator">++class="token punctuation">)class="token punctuation">{stdclass="token operator">::string threadnameclass="token operator">=class="token string">"thread-"class="token operator">+stdclass="token operator">::class="token function">to_stringclass="token punctuation">(iclass="token operator">+class="token number">1class="token punctuation">)class="token punctuation">;_threadsclass="token punctuation">.class="token function">emplace_backclass="token punctuation">(threadnameclass="token punctuation">,funcclass="token punctuation">)class="token punctuation">;class="token function">LOGclass="token punctuation">(DEBUGclass="token punctuation">,class="token string">"construct thread %s done, init success.\n"class="token punctuation">,threadnameclass="token punctuation">.class="token function">c_strclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">;class="token punctuation">}class="token punctuation">}class="token keyword">void class="token function">Startclass="token punctuation">(class="token punctuation">)class="token punctuation">{_isrunningclass="token operator">=class="token boolean">trueclass="token punctuation">;class="token keyword">forclass="token punctuation">(class="token keyword">autoclass="token operator">& threadclass="token operator">:_threadsclass="token punctuation">)class="token punctuation">{class="token function">LOGclass="token punctuation">(DEBUGclass="token punctuation">,class="token string">"Start thread %s done.\n"class="token punctuation">,threadclass="token punctuation">.class="token function">Nameclass="token punctuation">(class="token punctuation">)class="token punctuation">.class="token function">c_strclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">;threadclass="token punctuation">.class="token function">Startclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token punctuation">}class="token punctuation">}class="token keyword">void class="token function">Stopclass="token punctuation">(class="token punctuation">)class="token punctuation">{class="token function">LockQueueclass="token punctuation">(class="token punctuation">)class="token punctuation">;_isrunningclass="token operator">=class="token boolean">falseclass="token punctuation">;class="token function">WakeupAllclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token function">UnlockQueueclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token function">LOGclass="token punctuation">(INFOclass="token punctuation">,class="token string">"Thread Pool Stop Success!\n"class="token punctuation">)class="token punctuation">;class="token punctuation">}class="token keyword">void class="token function">Equeueclass="token punctuation">(class="token keyword">const T class="token operator">&inclass="token punctuation">)class="token punctuation">{class="token function">LockQueueclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token keyword">ifclass="token punctuation">(_isrunningclass="token punctuation">)class="token punctuation">{_task_queueclass="token punctuation">.class="token function">pushclass="token punctuation">(inclass="token punctuation">)class="token punctuation">;class="token comment">// 如果当前有线程在等待࿰c;需要唤醒class="token keyword">ifclass="token punctuation">(_sleep_thread_numclass="token operator">>class="token number">0class="token punctuation">)class="token punctuation">{class="token function">Wakeupclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token punctuation">}class="token punctuation">}class="token function">UnlockQueueclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token punctuation">}class="token operator">~class="token function">ThreadPoolclass="token punctuation">(class="token punctuation">)class="token punctuation">{class="token function">pthread_mutex_destroyclass="token punctuation">(class="token operator">&_mutexclass="token punctuation">)class="token punctuation">;class="token function">pthread_cond_destroyclass="token punctuation">(class="token operator">&_condclass="token punctuation">)class="token punctuation">;class="token punctuation">}
class="token keyword">privateclass="token operator">:class="token keyword">int _thread_numclass="token punctuation">;stdclass="token operator">::vectorclass="token operator"><Threadclass="token operator">> _threadsclass="token punctuation">;  class="token comment">// 管理多个线程stdclass="token operator">::queueclass="token operator"><Tclass="token operator">> _task_queueclass="token punctuation">; class="token comment">// 任务队列class="token keyword">bool _isrunningclass="token punctuation">; class="token comment">//当前线程是否在工作class="token keyword">int _sleep_thread_numclass="token punctuation">;   class="token comment">//计数器:休眠的线程个数pthread_mutex_t _mutexclass="token punctuation">;pthread_cond_t _condclass="token punctuation">;
class="token punctuation">}class="token punctuation">;code>
<code class="prism language-cpp">class="token comment">//Main.cc
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string">"ThreadPool.hpp"
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string">"Task.hpp"
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string">"Log.hpp"
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><memory>class="token keyword">using stdclass="token operator">::cinclass="token punctuation">;
class="token keyword">using stdclass="token operator">::coutclass="token punctuation">;
class="token keyword">using stdclass="token operator">::endlclass="token punctuation">;
class="token keyword">using class="token keyword">namespace log_nsclass="token punctuation">;class="token keyword">int class="token function">mainclass="token punctuation">(class="token punctuation">)
class="token punctuation">{class="token function">EnableScreenclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token comment">//std::unique_ptr<ThreadPool> tp=std::make_unique<>();  //构建一个ThreadPool对象ThreadPoolclass="token operator"><Taskclass="token operator">> class="token operator">*tpclass="token operator">=class="token keyword">new ThreadPoolclass="token operator"><Taskclass="token operator">>class="token punctuation">(class="token punctuation">)class="token punctuation">;tpclass="token operator">->class="token function">Initclass="token punctuation">(class="token punctuation">)class="token punctuation">;tpclass="token operator">->class="token function">Startclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token keyword">int cntclass="token operator">=class="token number">10class="token punctuation">;class="token keyword">while class="token punctuation">(cntclass="token punctuation">)class="token punctuation">{class="token comment">// 不断地向线程池推送任务class="token function">sleepclass="token punctuation">(class="token number">1class="token punctuation">)class="token punctuation">;Task class="token function">tclass="token punctuation">(class="token number">1class="token punctuation">,class="token number">1class="token punctuation">)class="token punctuation">;tpclass="token operator">->class="token function">Equeueclass="token punctuation">(tclass="token punctuation">)class="token punctuation">;class="token function">LOGclass="token punctuation">(INFOclass="token punctuation">,class="token string">"equeue a task, %s\n"class="token punctuation">,tclass="token punctuation">.class="token function">debugclass="token punctuation">(class="token punctuation">)class="token punctuation">.class="token function">c_strclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">;class="token function">sleepclass="token punctuation">(class="token number">1class="token punctuation">)class="token punctuation">;class="token punctuation">}tpclass="token operator">->class="token function">Stopclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token function">LOGclass="token punctuation">(INFOclass="token punctuation">,class="token string">"thread pool stop!\n"class="token punctuation">)class="token punctuation">;class="token function">sleepclass="token punctuation">(class="token number">10class="token punctuation">)class="token punctuation">;class="token keyword">return class="token number">0class="token punctuation">;
class="token punctuation">}
code>
<code class="prism language-cpp">class="token comment">// Thread.hpp
class="token macro property">class="token directive-hash">#class="token directive keyword">pragma class="token expression">once
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string"><pthread.h>
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string"><iostream>
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string"><string>
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><functional>class="token keyword">namespace threadModel
class="token punctuation">{class="token comment">// 线程执行的方法class="token comment">//typedef void (*func_t)(ThreadData* td);class="token keyword">using func_tclass="token operator">=stdclass="token operator">::functionclass="token operator"><class="token keyword">voidclass="token punctuation">(class="token keyword">const stdclass="token operator">::stringclass="token operator">&class="token punctuation">)class="token operator">>class="token punctuation">;class="token keyword">class class="token class-name">Threadclass="token punctuation">{class="token keyword">publicclass="token operator">:class="token keyword">void class="token function">Excuteclass="token punctuation">(class="token punctuation">)class="token punctuation">{_isrunning class="token operator">= class="token boolean">trueclass="token punctuation">;class="token function">_funcclass="token punctuation">(_nameclass="token punctuation">)class="token punctuation">;_isrunning class="token operator">= class="token boolean">falseclass="token punctuation">;class="token punctuation">}class="token keyword">publicclass="token operator">:class="token function">Threadclass="token punctuation">(class="token keyword">const stdclass="token operator">::string class="token operator">&nameclass="token punctuation">, func_t funcclass="token punctuation">) class="token operator">: class="token function">_nameclass="token punctuation">(nameclass="token punctuation">)class="token punctuation">, class="token function">_funcclass="token punctuation">(funcclass="token punctuation">)class="token punctuation">{class="token punctuation">}class="token comment">// void *ThreadRoutine(void* args)实际上参数里面还有一个Thread* thisclass="token keyword">static class="token keyword">void class="token operator">*class="token function">ThreadRoutineclass="token punctuation">(class="token keyword">void class="token operator">*argsclass="token punctuation">) class="token comment">// 加上static后࿰c;参数里面就没有Thread* thisclass="token punctuation">{Thread class="token operator">*self class="token operator">= class="token keyword">static_castclass="token operator"><Thread class="token operator">*class="token operator">>class="token punctuation">(argsclass="token punctuation">)class="token punctuation">; class="token comment">// 获得当前对象selfclass="token operator">->class="token function">Excuteclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token keyword">return class="token keyword">nullptrclass="token punctuation">;class="token punctuation">}class="token keyword">bool class="token function">Startclass="token punctuation">(class="token punctuation">)class="token punctuation">{class="token keyword">int n class="token operator">= class="token operator">::class="token function">pthread_createclass="token punctuation">(class="token operator">&_tidclass="token punctuation">, class="token keyword">nullptrclass="token punctuation">, ThreadRoutineclass="token punctuation">, class="token keyword">thisclass="token punctuation">)class="token punctuation">;class="token keyword">if class="token punctuation">(n class="token operator">!= class="token number">0class="token punctuation">)class="token keyword">return class="token boolean">falseclass="token punctuation">;class="token keyword">return class="token boolean">trueclass="token punctuation">;class="token punctuation">}stdclass="token operator">::string class="token function">Statusclass="token punctuation">(class="token punctuation">)class="token punctuation">{class="token keyword">if class="token punctuation">(_isrunningclass="token punctuation">)class="token keyword">return class="token string">"running"class="token punctuation">;class="token keyword">elseclass="token keyword">return class="token string">"sleep"class="token punctuation">;class="token punctuation">}class="token keyword">void class="token function">Stopclass="token punctuation">(class="token punctuation">)class="token punctuation">{class="token keyword">if class="token punctuation">(_isrunningclass="token punctuation">)class="token punctuation">{class="token function">pthread_cancelclass="token punctuation">(_tidclass="token punctuation">)class="token punctuation">;_isrunning class="token operator">= class="token boolean">falseclass="token punctuation">;class="token punctuation">}class="token punctuation">}class="token keyword">void class="token function">Joinclass="token punctuation">(class="token punctuation">)class="token punctuation">{class="token function">pthread_joinclass="token punctuation">(_tidclass="token punctuation">, class="token keyword">nullptrclass="token punctuation">)class="token punctuation">;class="token punctuation">}stdclass="token operator">::string class="token function">Nameclass="token punctuation">(class="token punctuation">)class="token punctuation">{class="token keyword">return _nameclass="token punctuation">;class="token punctuation">}class="token operator">~class="token function">Threadclass="token punctuation">(class="token punctuation">)class="token punctuation">{class="token function">Stopclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token punctuation">}class="token keyword">privateclass="token operator">:stdclass="token operator">::string _nameclass="token punctuation">;pthread_t _tidclass="token punctuation">;class="token keyword">bool _isrunningclass="token punctuation">;func_t _funcclass="token punctuation">; class="token comment">// 线程执行的回调函数class="token punctuation">}class="token punctuation">;
class="token punctuation">}
code>
<code class="prism language-cpp">class="token comment">//Task.hpp
class="token macro property">class="token directive-hash">#class="token directive keyword">pragma class="token expression">once
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><iostream>
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><string>
class="token macro property">class="token directive-hash">#class="token directive keyword">includeclass="token string"><functional>class="token keyword">class class="token class-name">Task
class="token punctuation">{class="token keyword">publicclass="token operator">:class="token function">Taskclass="token punctuation">(class="token punctuation">)class="token punctuation">{class="token punctuation">}class="token function">Taskclass="token punctuation">(class="token keyword">int xclass="token punctuation">,class="token keyword">int yclass="token punctuation">)class="token operator">:class="token function">_xclass="token punctuation">(xclass="token punctuation">)class="token punctuation">,class="token function">_yclass="token punctuation">(yclass="token punctuation">)class="token punctuation">{class="token punctuation">}class="token keyword">void class="token function">Excuteclass="token punctuation">(class="token punctuation">)class="token punctuation">{_resultclass="token operator">=_xclass="token operator">+_yclass="token punctuation">;class="token punctuation">}class="token keyword">void class="token keyword">operatorclass="token punctuation">(class="token punctuation">)class="token punctuation">(class="token punctuation">)class="token punctuation">{class="token function">Excuteclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token punctuation">}stdclass="token operator">::string class="token function">debugclass="token punctuation">(class="token punctuation">)class="token punctuation">{stdclass="token operator">::string msgclass="token operator">=stdclass="token operator">::class="token function">to_stringclass="token punctuation">(_xclass="token punctuation">)class="token operator">+class="token string">"+"class="token operator">+stdclass="token operator">::class="token function">to_stringclass="token punctuation">(_yclass="token punctuation">)class="token operator">+class="token string">"=?"class="token punctuation">;class="token keyword">return msgclass="token punctuation">;class="token punctuation">}stdclass="token operator">::string class="token function">resultclass="token punctuation">(class="token punctuation">)class="token punctuation">{stdclass="token operator">::string msgclass="token operator">=stdclass="token operator">::class="token function">to_stringclass="token punctuation">(_xclass="token punctuation">)class="token operator">+class="token string">"+"class="token operator">+stdclass="token operator">::class="token function">to_stringclass="token punctuation">(_yclass="token punctuation">)class="token operator">+class="token string">"="class="token operator">+stdclass="token operator">::class="token function">to_stringclass="token punctuation">(_resultclass="token punctuation">)class="token punctuation">;class="token keyword">return msgclass="token punctuation">;class="token punctuation">}class="token keyword">privateclass="token operator">:class="token keyword">int _xclass="token punctuation">;class="token keyword">int _yclass="token punctuation">;class="token keyword">int _resultclass="token punctuation">;
class="token punctuation">}class="token punctuation">;
code>

c="https://i-blog.csdnimg.cn/direct/fc75d936089b4e1a8ca598ba07a38c54.png" alt="在这里插入图片描述" />

c="https://i-blog.csdnimg.cn/direct/fd02fc1cefac4efca17575c7351e687d.gif#pic_center" alt="在这里插入图片描述" />

class="blog-extension-box">

http://www.ppmy.cn/news/1534757.html

相关文章

Python - PDF 转 png

网上搜了下很多方法都是过期的&#xff0c;这里贴下我的方法 根据 pymupdf – Pixmap.tobytes https://pymupdf.readthedocs.io/en/latest/pixmap.html#Pixmap.tobytes 核心方法 def pdf2png(pdfPath, img_dir, zoom_x1,zoom_y1,rotation_angle0):# 打开PDF文件pdf fitz.open…

Redis数据库与GO完结篇:redis操作总结与GO使用redis

一、redis操作总结 由于写redis命令的时候有提示符&#xff0c;所以下表只给出命令名称 数据类型操作简介字符串GET, SET, MGET, MSET, SETEX,DEL最基本的数据类型&#xff0c;存储任意二进制数据&#xff0c;支持简单操作和原子计数。适合存储重复数据。哈希HSET, HGET, HDE…

vue2接入高德地图实现折线绘制、起始点标记和轨迹打点的完整功能(提供Gitee源码)

目录 一、申请密钥 二、安装element-ui 三、安装高德地图依赖 四、完整代码 五、运行截图 六、官方文档 七、Gitee源码 一、申请密钥 登录高德开放平台&#xff0c;点击我的应用&#xff0c;先添加新应用&#xff0c;然后再添加Key。 ​ 如图所示填写对应的信息&…

不同环境不同的配置文件;不同地区的数据库连接

不同地区的数据库不同&#xff0c;是怎么找到不同的数据库的 在Spring Boot项目中&#xff0c;如果存在application.yml、application-test.yml、application-prod.yml等多个配置文件&#xff0c;Spring Boot会根据当前激活的配置文件环境来决定使用哪个配置文件。以下是关于如…

基于Spring Boot+Vue前后端分离的中医药科普系统设计和实现(协同过滤算法)【原创】

&#x1f388;系统亮点&#xff1a;协同过滤算法&#xff1b; 一.系统开发工具与环境搭建 1.系统设计开发工具 后端使用Java编程语言的Spring boot框架 项目架构&#xff1a;B/S架构 运行环境&#xff1a;win10/win11、jdk17 前端&#xff1a; 技术&#xff1a;框架Vue.js&am…

C++11中智能指针以及标准模板库 My_string My_stack

My_string.h #ifndef MY_STRING_H #define MY_STRING_H#include <iostream> #include <cstring> #include <stdexcept>using namespace std;template<typename T> class My_string { private:T *ptr; // 指向字符数组的指针int size; /…

计算机毕业设计Hadoop+Spark知识图谱美团美食推荐系统 美团餐厅推荐系统 美团推荐系统 美食价格预测 美团爬虫 美食数据分析 美食可视化大屏

《HadoopSpark知识图谱美团美食推荐系统》开题报告 一、研究背景与意义 随着互联网技术的快速发展&#xff0c;大数据已成为企业竞争力的关键要素。美团作为国内领先的本地生活服务平台&#xff0c;拥有海量的用户行为数据和丰富的业务场景。然而&#xff0c;面对如此庞大的数…

leetcode练习 路径总和II

给你二叉树的根节点 root 和一个整数目标和 targetSum &#xff0c;找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。 叶子节点 是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a;root [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum 22 输出&a…