当前位置:   article > 正文

std::thread暂停、挂起及挂起后恢复执行的功能实现_c++ thread停止之后还能再次运行吗

c++ thread停止之后还能再次运行吗

目录

1. 前言

2. 线程挂起、挂起后继续执行的需求举例

3. 功能实现

4. 后记


1. 前言

       C++11提供了std::thread类,用于多线程编程。当构造一个std::thread对象时,线程就开始运行了,如:

std::thread* pMythread = new std::thread(threadFun, threadParm1,  threadParm2, .....,  threadParmN);

其中threadFun为线程的执行函数,可以是一般函数、类的成员函数、lamba表达式等, threadParm1,  threadParm2, .... threadParamN为线程参数。更多关于std::thread的用法,请参见如下链接:

std::thread类中的所有方法中,都没有暂停、挂起及挂起后继续执行的方法,如何实现线程暂停、挂起、挂起后恢复执行?

2. 线程挂起、挂起后继续执行的需求举例

       现实中,经常会遇到需要线程暂时挂起,等某个条件符合后再继续运行。如:在有多个Tab页的窗体中,每个tab页开启了一个线程处理某个业务,但每次只有一个tab页为当前页,即用户在某一时刻只能面对一个tab页、处理一个tab页。如下:

上图界面说明如下:

  • 该窗体有两个tab页,即Tab1、Tab2。
  • 当Tab1为当前页面,此时Tab2页面对用户是不可见的。
  • 当Tab2为当前页面,此时Tab1页面对用户是不可见的。
  •  Tab1、Tab2页面在后台都开启了一个线程处理业务。

       为了提高CPU利用率,当用户在当前页面Tab1时,要将Tab2中的线程暂停;而当用户切换到Tab2即Tab2为当前页面时,要将Tab2中的线程恢复运行,且还要将要将Tab1中的线程暂停。

3. 功能实现

      编写代码如下:

Thread.h

  1. #define THREAD_H
  2. #include <thread>
  3. #include <atomic>
  4. #include <mutex>
  5. #include <condition_variable>
  6. class Thread
  7. {
  8. public:
  9. Thread();
  10. virtual ~Thread();
  11. enum State
  12. {
  13. Stoped, ///<停止状态,包括从未启动过和启动后被停止
  14. Running, ///<运行状态
  15. Paused ///<暂停状态
  16. };
  17. State state() const;
  18. void start();
  19. void stop();
  20. void pause();
  21. void resume();
  22. protected:
  23. virtual void process() = 0;
  24. private:
  25. void run();
  26. private:
  27. std::thread* _thread;
  28. std::mutex _mutex;
  29. std::condition_variable _condition;
  30. std::atomic_bool _pauseFlag; ///<暂停标识
  31. std::atomic_bool _stopFlag; ///<停止标识
  32. State _state;
  33. };

 Thread.cpp

  1. #include "Thread.h"
  2. #include <iostream>
  3. using namespace std;
  4. Thread::Thread()
  5. : _thread(nullptr),
  6. _pauseFlag(false),
  7. _stopFlag(false),
  8. _state(Stoped)
  9. {
  10. }
  11. Thread::~Thread()
  12. {
  13. stop();
  14. }
  15. Thread::State Thread::state() const
  16. {
  17. return _state;
  18. }
  19. void Thread::start()
  20. {
  21. if (_thread == nullptr)
  22. {
  23. _thread = new thread(&amp;Thread::run, this);
  24. _pauseFlag = false;
  25. _stopFlag = false;
  26. _state = Running;
  27. }
  28. }
  29. void Thread::stop()
  30. {
  31. if (_thread != nullptr)
  32. {
  33. _pauseFlag = false;
  34. _stopFlag = true;
  35. _condition.notify_all(); // Notify one waiting thread, if there is one.
  36. _thread->join(); // wait for thread finished
  37. delete _thread;
  38. _thread = nullptr;
  39. _state = Stoped;
  40. }
  41. }
  42. void Thread::pause()
  43. {
  44. if (_thread != nullptr)
  45. {
  46. _pauseFlag = true;
  47. _state = Paused;
  48. }
  49. }
  50. void Thread::resume()
  51. {
  52. if (_thread != nullptr)
  53. {
  54. _pauseFlag = false;
  55. _condition.notify_all();
  56. _state = Running;
  57. }
  58. }
  59. void Thread::run()
  60. {
  61. cout << "enter thread:" << this_thread::get_id() << endl;
  62. while (!_stopFlag)
  63. {
  64. process();
  65. if (_pauseFlag)
  66. {
  67. unique_lock<mutex> locker(_mutex);
  68. while (_pauseFlag)
  69. {
  70. _condition.wait(locker); // Unlock _mutex and wait to be notified
  71. }
  72. locker.unlock();
  73. }
  74. }
  75. _pauseFlag = false;
  76. _stopFlag = false;
  77. cout << "exit thread:" << this_thread::get_id() << endl;
  78. }

main.cpp

  1. #include <QCoreApplication>
  2. #include <iostream>
  3. #include "Thread.h"
  4. using namespace std;
  5. void mySleep(int s)
  6. {
  7. std::this_thread::sleep_for(std::chrono::duration<double>(s));
  8. }
  9. class MyThread : public Thread
  10. {
  11. protected:
  12. virtual void process() override
  13. {
  14. cout << "do my something" << endl;
  15. mySleep(1);
  16. }
  17. };
  18. int main(int argc, char *argv[])
  19. {
  20. QCoreApplication a(argc, argv); // 采用Qt控制台程序测试
  21. MyThread thread;
  22. cout << "start thread" << endl;
  23. thread.start();
  24. cout << "thread state:" << thread.state() << endl;
  25. mySleep(3);
  26. cout << "pause thread" << endl;
  27. thread.pause();
  28. cout << "thread state:" << thread.state() << endl;
  29. mySleep(3);
  30. cout << "resume thread" << endl;
  31. thread.resume();
  32. cout << "thread state:" << thread.state() << endl;
  33. mySleep(3);
  34. cout << "stop thread" << endl;
  35. thread.stop();
  36. cout << "thread state:" << thread.state() << endl;
  37. mySleep(3);
  38. return a.exec();
  39. }

结果如下:

4. 后记

     对于2节提到的需求例子,可以捕捉Tab页切换、改变事件,响应该事件,从而使相应的线程挂起或恢复执行。 

     对于run函数中的挂起代码如下:

  1. if (_pauseFlag)
  2. {
  3. unique_lock<mutex> locker(_mutex);
  4. while (_pauseFlag)
  5. {
  6. _condition.wait(locker); // Unlock _mutex and wait to be notified
  7. }
  8. locker.unlock();
  9. }

可否改为如下那样呢?

  1. if (_pauseFlag)
  2. {
  3. unique_lock<mutex> locker(_mutex);
  4. _condition.wait(locker); // Unlock _mutex and wait to be notified
  5. }

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

闽ICP备14008679号