C++11 – 封装std::thread,增加子线程启动、暂停、唤起、停止功能
本文作者:StubbornHuang
版权声明:本文为站长原创文章,如果转载请注明原文链接!
原文标题:C++11 – 封装std::thread,增加子线程启动、暂停、唤起、停止功能
原文链接:https://www.stubbornhuang.com/1766/
发布于:2021年10月21日 13:28:46
修改于:2021年10月27日 9:42:34
1 封装std::thread,增加子线程启动、暂停、唤起、停止功能
C++标准库的std::thread已经为C++增加了很好的跨平台多线程编程体验,程序员只需要使用标准库std::thread就可以写出很好的多线程并发程序。但是在std::thread中对线程的控制需要自主控制。
我们经常会在子线程函数中写一个while循环去处理队列任务,当任务全部处理完成之后需要挂起线程,减少CPU负载,所以对应这个需求对std::thread进行了封装,实现一个扩展的std::thread基类,在基类中提供开启线程、暂停线程、唤起线程、停止线程的函数,并提供一个纯虚函数接口CustomRun,用于在子类中扩展自己的线程处理函数。
1.1 封装代码
代码如下:
ThreadExtension.h
#ifndef THREAD_EXTENSION_H
#define THREAD_EXTENSION_H
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
class ThreadExtension
{
enum class ThreadState
{
Stoped = 0,
Running = 1,
Paused = 2
};
public:
ThreadExtension();
virtual~ThreadExtension();
public:
void StartThread();
void PauseThread();
void ResumeThread();
void StopThread();
int GetThreadState() const;
private:
void Run();
protected:
virtual void CustomRun() {};
private:
ThreadState m_Thread_State;
std::shared_ptr<std::thread> m_pThread;
std::mutex m_Mutex;
std::condition_variable m_Condition_Variable;
std::atomic<bool> m_Thread_Pause_Flag;
std::atomic<bool> m_Thread_Stop_Flag;
};
#endif // !THREAD_EXTENSION_H
ThreadExtension.cpp
#include "ThreadExtension.h"
ThreadExtension::ThreadExtension()
:m_pThread(nullptr),
m_Thread_Pause_Flag(false),
m_Thread_Stop_Flag(false),
m_Thread_State(ThreadState::Stoped)
{
}
ThreadExtension::~ThreadExtension()
{
StopThread();
}
void ThreadExtension::StartThread()
{
if (m_pThread == nullptr)
{
m_pThread = std::make_shared<std::thread>(&ThreadExtension::Run, this);
if (m_pThread != nullptr)
{
m_Thread_Pause_Flag = false;
m_Thread_Stop_Flag = false;
m_Thread_State = ThreadState::Running;
}
}
}
void ThreadExtension::PauseThread()
{
if (m_pThread != nullptr)
{
if (m_Thread_State == ThreadState::Running)
{
m_Thread_Pause_Flag = true;
m_Thread_State = ThreadState::Paused;
}
}
}
void ThreadExtension::ResumeThread()
{
if (m_pThread != nullptr)
{
if (m_Thread_State == ThreadState::Paused)
{
m_Thread_Pause_Flag = false;
m_Condition_Variable.notify_all();
m_Thread_State = ThreadState::Running;
}
}
}
void ThreadExtension::StopThread()
{
if (m_pThread != nullptr)
{
m_Thread_Stop_Flag = true;
m_Thread_Pause_Flag = false;
m_Condition_Variable.notify_all();
if (m_pThread->joinable())
{
m_pThread->join();
}
// 释放
m_pThread.reset();
if (m_pThread == nullptr)
{
m_Thread_State = ThreadState::Stoped;
}
}
}
int ThreadExtension::GetThreadState() const
{
return (int)m_Thread_State;
}
void ThreadExtension::Run()
{
while (!m_Thread_Stop_Flag)
{
// 指定自定义线程操作
try
{
CustomRun();
}
catch (std::exception& e)
{
break;
}
// 暂停
if (m_Thread_Pause_Flag)
{
std::unique_lock<std::mutex> thread_locker(m_Mutex);
if (m_Thread_Pause_Flag)
{
// 等待互斥锁
m_Condition_Variable.wait(thread_locker);
}
thread_locker.unlock();
}
}
m_Thread_Pause_Flag = false;
m_Thread_Stop_Flag = false;
}
在上述ThreadExtension类中,在StartThread函数中创建了一个以成员函数Run为线程函数的子线程,在Run函数中通过原子bool变量m_Thread_Stop_Flag控制线程函数开始或者停止,通过原子变量m_Thread_Pause_Flag控制线程函数暂停或者唤醒,在m_Thread_Pause_Flag为真时,使用std::condition_variable和std::mutex等待线程函数被重新唤醒继续执行。
1.2 使用示例
#include <iostream>
#include "ThreadExtension.h"
class TestThread :public ThreadExtension
{
public:
TestThread()
{
}
virtual ~TestThread()
{
}
void CustomRun() override
{
std::cout << "CustomRun" << std::endl;
}
};
int main()
{
TestThread thread;
std::cout << "Thread State:" << thread.GetThreadState() << std::endl;
thread.StartThread();
std::cout << "Thread State:" << thread.GetThreadState() << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
thread.PauseThread();
std::cout << "Thread State:" << thread.GetThreadState() << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(11100));
thread.ResumeThread();
std::cout << "Thread State:" << thread.GetThreadState() << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
thread.StopThread();
std::cout << "Thread State:" << thread.GetThreadState() << std::endl;
getchar();
return 0;
}
运行结果:
当前分类随机文章推荐
- C++ 11 - final关键字简要介绍 阅读2015次,点赞0次
- C++ - queue存储动态指针时正确释放内存 阅读5512次,点赞2次
- C++11 - 构建一个符合实际应用要求的线程池 阅读1146次,点赞0次
- C++ - std::string字符串格式化方法总结 阅读874次,点赞0次
- C++ - 最简单的将文本文件的内容一次性读取到std::string的方法 阅读4857次,点赞4次
- C++11 - 快速学会正则表达式 阅读1379次,点赞2次
- C++ - 数组初始化 阅读349次,点赞0次
- C++11 - 父类与子类相互包含的时候该如何正确的使用智能指针,防止循环引用 阅读2584次,点赞0次
- C++ - single header跨平台高效开源日志库Easylogging++的配置和使用 阅读538次,点赞0次
- C++ - Windows和Linux系统下获取当前可执行程序的绝对路径 阅读2143次,点赞0次
全站随机文章推荐
- 资源分享 - 精通Python网络爬虫 核心技术、框架与项目实战 ,韦玮著 高清PDF下载 阅读1936次,点赞0次
- C++ - 求解std::vector
中topk数值以及topk数值对应的索引 阅读2414次,点赞0次 - 资源分享 - Non-Photorealistic Computer Graphics - Modeling, Rendering, and Animation 英文高清PDF下载 阅读1850次,点赞0次
- 资源分享 - 深度学习实战(杨云杜飞 清华大学出版社)高清pdf下载 阅读2419次,点赞0次
- 资源分享 - ShaderX3 - Advanced Rendering with DirectX and OpenGL 英文高清PDF下载 阅读2244次,点赞0次
- 资源分享 - Introduction to Computer Graphics - A Practical Learning Approach 英文高清PDF下载 阅读1122次,点赞0次
- FFmpeg - ./configure编译参数全部总结和整理 阅读1750次,点赞3次
- C++11 - 父类与子类相互包含的时候该如何正确的使用智能指针,防止循环引用 阅读2584次,点赞0次
- WordPress - 在每一个文章内容末尾都加一个作者信息展示框 阅读2132次,点赞0次
- 资源分享 - Game Engine Gems 3英文高清PDF下载 阅读2667次,点赞1次
评论
169