循环计时器线程

时间:2019-05-28 12:06:32

标签: c++ timer chrono

我想为循环计时器创建线程池:每n秒,我们将运行任务。

在我的示例中,我们有两个任务。对于每个任务,我将创建一个线程来运行。我为每个任务添加了状态条件,如果状态为false,我们什么也不做。我需要状态来控制计时器,我可以调用计时器的启动/停止(抱歉,在此代码中,只有启动功能)。

这是我的代码:

 #include <iostream>
#include <list>
#include <functional>
#include <map>
#include <thread>
#include <chrono>
#include <vector>
#include <mutex>

//using namespace std::chrono_literals;

void print_time()
{
    std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
    std::chrono::system_clock::duration tp = now.time_since_epoch();
    tp -= std::chrono::duration_cast<std::chrono::seconds>(tp);
    std::time_t ttp = std::chrono::system_clock::to_time_t(now);
    tm t = *gmtime(&ttp);

    std::printf("[%04u-%02u-%02u %02u:%02u:%02u.%03u]: ", t.tm_year + 1900,
                t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec,
                static_cast<unsigned>(tp/std::chrono::milliseconds(1)));
}

typedef std::function<void()> Callback;

enum E_NUM {
    NUM_ONE = 0,
    NUM_TWO
};

class Foo {
    public:
        static Foo& getInstance()
        {
            static Foo instance;
            return instance;
        }

        void init() {
            m_mapThreadStatus[NUM_ONE] = false;
            m_mapThreadStatus[NUM_TWO] = false;
            m_mapCallback[NUM_ONE] = std::bind(&Foo::test, this);
            m_mapCallback[NUM_TWO] = std::bind(&Foo::foo_test, this);
        }

        void addTimer(E_NUM id, int num_seconds) {
            std::thread th ([id, num_seconds] () {
                    std::cout << std::this_thread::get_id() << " id: " << id << "\tseconds: " << num_seconds << std::endl;
                    while (1)
                    {
                        if ( Foo::getInstance().getStatus(id) == true)
                        {
                            Foo::getInstance().callfunctor(id);
                            std::this_thread::sleep_for(std::chrono::seconds(num_seconds));
                        }
                        else
                        {
                        }
                        //std::this_thread::sleep_for(std::chrono::seconds(num_seconds));
                    }
                });
            m_mapThreads[id] = std::move(th);
        }

        void callfunctor(E_NUM id) {
            m_mapCallback[id]();
        }

        void startTimers(E_NUM id) {    
            m_mapThreadStatus[id] = true;
            if (m_mapThreads[id].joinable())
            {
                m_mapThreads[id].join();
            }
        }

        bool getStatus(E_NUM id) { 
            return m_mapThreadStatus[id];}

    private:
        void test() {
            print_time();
            std::cout << std::this_thread::get_id() << std::endl;
            std::cout << "\033[1;31m" << __PRETTY_FUNCTION__ << "\033[0m" << std::endl;
        }
        void foo_test() {
            print_time();
            std::cout << std::this_thread::get_id() << std::endl;
            std::cout << "\033[1;32m" << __PRETTY_FUNCTION__ << "\033[0m" << std::endl;
        }
        Foo() {init();}
        std::map<E_NUM, Callback> m_mapCallback;
        std::vector<std::thread> m_threads;
        std::map<E_NUM, std::thread> m_mapThreads;
        std::map<E_NUM, bool> m_mapThreadStatus;
};

int main()
{
    Foo::getInstance().addTimer(NUM_ONE, 1);
    Foo::getInstance().addTimer(NUM_TWO, 2);
    Foo::getInstance().startTimers(NUM_ONE);
    Foo::getInstance().startTimers(NUM_TWO);
    return 0;
}

但是我的问题是: 1.似乎只有一项任务在运行,而不是预期的两项。

40557398533888 id: 0    seconds: 1140557390141184 id: 1 seconds: 2
[2019-05-28 11:56:49.770]: 140557398533888
void Foo::test()

[2019-05-28 11:56:50.770]: 140557398533888
void Foo::test()
[2019-05-28 11:56:51.771]: 140557398533888
void Foo::test()
[2019-05-28 11:56:52.771]: 140557398533888
void Foo::test()
[2019-05-28 11:56:53.772]: 140557398533888
void Foo::test()
  1. 经典问题:当我们创建std :: thread时,它会立即运行,对吗?例如,link。那么,如何在添加计时器后改善我的代码以启动?

编辑1:

我在Foo中添加了该功能:

class Foo {
    ...
    void startTimers() {
        m_mapThreads[NUM_ONE].join();
        m_mapThreads[NUM_TWO].join();
    }
};

我在main的END处调用此函数,它的作用就像是一个魅力。谢谢。

1 个答案:

答案 0 :(得分:3)

考虑您的 <widget xmlns="http://www.w3.org/ns/widgets" xmlns:gap="http://phonegap.com/ns/1.0"id="com.mitraye.earthinfosys" version="6.5.0"> <name>Earth Infosys</name> <description></description> <description></description> <author href="http://mitraye.com" email="support@mitraye.com">Mitraye</author> <content src="index.html"/> <preference name="permissions" value="none"/> <preference name="phonegap-version" value="cli-6.5.0" /> <preference name="orientation" value="default"/> <preference name="target-device" value="universal"/> <preference name="fullscreen" value="true"/> <preference name="webviewbounce" value="true"/> <preference name="prerendered-icon" value="true"/> <preference name="stay-in-webview" value="false"/> <preference name="ios-statusbarstyle" value="black-opaque"/> <preference name="detect-data-types" value="true"/> <preference name="exit-on-suspend" value="false"/> <preference name="show-splash-screen-spinner" value="true"/> <preference name="auto-hide-splash-screen" value="true"/> <preference name="disable-cursor" value="false"/> <preference name="windows-arch" value="anycpu" /> <preference name="android-minSdkVersion" value="20" /> <preference name="android-targetSdkVersion" value="28" /> <preference name="android-maxSdkVersion" value="28" /> <preference name="android-installLocation" value="auto"/> <plugin name="cordova-plugin-battery-status" source="npm" spec="~1.1.1"/> <plugin name="cordova-plugin-camera" source="npm" spec="~2.1.1"/> <plugin name="cordova-plugin-media-capture" source="npm" spec="~1.2.0"/> <plugin name="cordova-plugin-console" source="npm" spec="~1.0.2"/> <plugin name="cordova-plugin-contacts" source="npm" spec="~2.0.1"/> <plugin name="cordova-plugin-device" source="npm" spec="~1.1.1"/> <plugin name="cordova-plugin-device-motion" source="npm" spec="~1.2.0"/> <plugin name="cordova-plugin-device-orientation" source="npm" spec="~1.0.2"/> <plugin name="cordova-plugin-dialogs" source="npm" spec="~1.2.0"/> <plugin name="cordova-plugin-file" source="npm" spec="~4.1.1"/> <plugin name="cordova-plugin-native-spinner" source="npm" spec="~1.1.3"/> <plugin name="cordova-plugin-file-transfer" source="npm" spec="~1.5.0"/> <plugin name="cordova-plugin-geolocation" source="npm" spec="~2.1.0"/> <plugin name="cordova-plugin-globalization" source="npm" spec="~1.0.3"/> <plugin name="cordova-plugin-inappbrowser" source="npm" spec="~1.3.0"/> <plugin name="cordova-plugin-media" source="npm" spec="~2.2.0"/> <plugin name="cordova-plugin-network-information" source="npm" spec="~1.2.0"/> <plugin name="cordova-plugin-splashscreen" source="npm" spec="~3.2.1"/> <plugin name="cordova-plugin-statusbar" source="npm" spec="~2.1.2"/> <plugin name="cordova-plugin-vibration" source="npm" spec="~2.1.0"/> <plugin name="cordova-plugin-whitelist" source="npm" spec="~1.2.1"/> <access origin="*"/> <allow-intent href="http://*/*"/> <allow-intent href="https://*/*"/> <allow-intent href="tel:*"/> <allow-intent href="sms:*"/> <allow-intent href="mailto:*"/> <allow-intent href="geo:*"/> <platform name="android"> <allow-intent href="market:*"/> </platform> <platform name="ios"> <allow-intent href="itms:*"/> <allow-intent href="itms-apps:*"/> </platform> <icon src="icon.png"/> <splash src="splash.png" /> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapp" android:versionCode="1" android:versionName="1.0" > <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> </manifest> <preference name="SplashScreenDelay" value="5000" /> <splash platform="android" qualifier="port-ldpi" src="res/android/screen- ldpi-portrait.png" /> <splash platform="android" qualifier="port-mdpi" src="res/android/screen- mdpi-portrait.png" /> <splash platform="android" qualifier="port-hdpi" src="res/android/screen- hdpi-portrait.png" /> <splash platform="android" qualifier="port-xhdpi" src="res/android/screen- xhdpi-portrait.png" /> </widget> 实施...

Foo::startTimers

void startTimers (E_NUM id) { m_mapThreadStatus[id] = true; if (m_mapThreads[id].joinable()) { m_mapThreads[id].join(); } } 用... {p}标识的线程。

start

但是您然后id那个线程。最终结果是,当您启动给定线程时,您的代码将阻塞,直到该线程完成为止。所以,有了...

m_mapThreadStatus[id] = true;

线路...

join

将阻塞,直到与int main() { Foo::getInstance().addTimer(NUM_ONE, 1); Foo::getInstance().addTimer(NUM_TWO, 2); Foo::getInstance().startTimers(NUM_ONE); Foo::getInstance().startTimers(NUM_TWO); return 0; } 关联的线程结束为止(在当前情况下永远不会),并且永远不会调用Foo::getInstance().startTimers(NUM_ONE);