可以直接使用c++11的thread, mutex, conditon_variable来实现, 结合了std::function.
Note:
1)start函数,开辟一个新的线程,并detach,在这个线程中周期性地执行task。
建立一个std::thread线程时,需要传入一个可调用对象,这里使用了lambda函数,非常方便。
start函数的入参是,周期时间ms,以及一个std::function2) 使用了c++11的原子变量automic
,比较方便。 3)stop函数的作用是给已经正在运行的任务线程发一个通知(通过改变一个bool成员变量),然后使用一个conditon_variable进入等待状态。
任务线程会在每次执行新一轮的任务时检查该变量的值,并判断是否停止, 停止后,会使用condition_variable通知stop函数不用等待了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | #pragma once #include <iostream> #include <mutex> #include <thread> #include <functional> #include <condition_variable> #include <atomic> using namespace std; class MyTimer { public: MyTimer() { expired = true; tryToExpire = false; } //interval: ms void start(int interval, std::function<void()> task) { if (expired == false)//has already started, do not start again return; // start async timer, launch thread and wait in that thread expired = false; //将lambda函数传递给线程,做线程函数 std::thread([this, interval, task]() { //小缺点:在task执行的过程中设置tryToExpire为true的话,需要等到本次task执行完毕后才能被while条件判断检测到。 while (!tryToExpire) { // sleep every interval and do the task again and again until times up std::this_thread::sleep_for(std::chrono::milliseconds(interval)); task(); //call this function every interval milliseconds. } // timer be stopped, update the condition variable expired and wake main thread std::lock_guard<std::mutex> locker(mut); expired = true; cv.notify_one(); }).detach(); } void stop()//该接口负责修改tryToExipired的值。 { // do not stop again if (expired) return; if (tryToExpire) return; // wait until timer tryToExpire = true; // change this bool value to make timer while loop stop. This val is atomic type. std::unique_lock<std::mutex> locker(mut); cv.wait(locker, [this] {return expired == true; });//不给lambda函数串this,不能使用成员变量expired! // reset the timer, //成功停止后,设置tryToExpire为false. 其实,可以不使用wait动作,将tryToExpire=false的动作放到 //start函数,当while循环被打断后,立即设置tryToExpire为false。 //但是,这样单独放在这里设置也有好处吧,实现了tryToExipired的值仅仅由该stop函数负责。例如,任务线程成功结束后,这里可以进行一些额外的善后动作, if (expired == true) tryToExpire = false; } private: condition_variable cv; mutex mut;//与cv配合 atomic<bool> expired; //timer stop status atomic<bool> tryToExpire;//timer is in stop process. }; |
Test:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | void printNum() { static int a = 0; a++; cout << "a=" << a << endl; } void main() { MyTimer obj; obj.start(1000,printNum); getchar();//定时线程执行了detatch,这里需要等待才能看到起输出数字到屏幕上 obj.stop(); getchar(); return; } |
Ref:
https://blog.csdn.net/u012234115/article/details/89857431
https://www.cnblogs.com/grandyang/p/4340948.html