Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在不让用户等待的情况下管理多个线程?_C++_Multithreading - Fatal编程技术网

C++ 如何在不让用户等待的情况下管理多个线程?

C++ 如何在不让用户等待的情况下管理多个线程?,c++,multithreading,C++,Multithreading,对不起,如果这句话用得不好,我不知道如何准确地描述我想要的标题。但基本上我的目标是让用户输入时间,让程序在时间过去时提醒他们。时间过后,程序会寻找另一个时间,同时允许用户输入更多的时间。基本上,它看起来是这样的: void printTime(tm time) { //sleep until time cout << "it is " << time << endl; lookForNextTime(); } void lookFor

对不起,如果这句话用得不好,我不知道如何准确地描述我想要的标题。但基本上我的目标是让用户输入时间,让程序在时间过去时提醒他们。时间过后,程序会寻找另一个时间,同时允许用户输入更多的时间。基本上,它看起来是这样的:

void printTime(tm time) {
    //sleep until time
    cout << "it is " << time << endl;
    lookForNextTime();
}

void lookForNextTime() {
    //find earliest time
    printTime(time);
}

int main() {
    //create thread in lookForNextTime
    while(true) {
        //ask user to insert more times until they quit
    }
}
void打印时间(tm时间){
//晚睡

Cuth

欢迎使用StActPox.C++中我对线程的处理是相当新的,所以我不熟悉最好的库和技术,但我可以至少分享一些我所知道的基础知识,希望这能让你感觉从哪里去。 如果我理解正确,我相信你们的问题主要围绕着

join()
展开

调用
join()
是在继续之前等待线程加入的方式,但您不必在创建线程后立即这样做,否则它将毫无意义。您可以让线程以自己的方式运行,当它完成时,它将结束,而无需来自主线程的任何进一步输入(请纠正我,我错了)

关于
join()
的重要一点是,在退出程序之前,您对所有线程调用它以等待它们(或者以某种方式安全地中止它们)。否则,即使在main()之后,它们也会继续运行返回并将在尝试访问内存时引发问题,因为它们不再连接到正在运行的进程。另一种可能的用途是在计算中让几个工作线程在某些检查点匹配,以便在获取下一个工作块之前共享结果

希望这能有所帮助。不过我还有一些想法,我想我会与大家分享,以防您或未来的读者不熟悉本示例中涉及的其他一些概念


您没有指出是否有一种方法可以跟踪时间并在线程之间共享时间,因此我只想给出一个快速提示:

在添加或弹出缓冲区之前锁定缓冲区。

这样做很重要,以避免争用情况,即一个线程可能试图弹出某些内容,而另一个线程正在添加并导致出现奇怪的问题,特别是如果您最终使用了诸如which排序之类的内容,并确保插入时任何给定元素只有一个副本

如果你不熟悉锁定机制,那么你可以在C++中找到使用互斥和信号量的例子,或者搜索“锁定”或“同步对象”。


就实际创建线程而言,我想到了两件事。一个想法是使用线程池。有几个库用于处理线程池,其中一个例子就是苹果的开源(通常称为libdispatch)它可以在Linux上使用,但对于Windows,您可能需要查找其他内容(不幸的是,我对Windows平台不太熟悉)。他们管理您正在使用和未使用的线程的生命周期,因此他们可能会提供帮助。再次,我本人对此有点陌生,我不能100%确定这对您来说是最好的事情,特别是因为您还有项目的其他部分要解决,但这可能值得一看

即使不使用线程池(比如说你使用pthreads),我也不认为你需要太担心自己启动一堆线程,只要你对它进行一些合理的限制(多少是合理的,我不确定,但如果您查看macOS中的Activity Monitor或Windows中的Task Manager或Linux中的TOP,您会发现在任何给定的时间,您机器上的许多程序可能正在运行相当多的线程,现在我有5090个线程正在运行,327个进程。这大约是每个进程15.5个线程。有些进程运行得很高呃)


希望有帮助。

欢迎StAcdPosiv.I是一个新的C++线程,所以我不熟悉最好的库和技术,但我可以至少分享一些我所知道的基础知识,希望这能让你感觉从哪里去。 如果我理解正确,我相信你们的问题主要围绕着

join()
展开

调用
join()
是在继续之前等待线程加入的方式,但您不必在创建线程后立即这样做,否则它将毫无意义。您可以让线程以自己的方式运行,当它完成时,它将结束,而无需来自主线程的任何进一步输入(请纠正我,我错了)

关于
join()
的重要一点是,在退出程序之前,您对所有线程调用它以等待它们(或者以某种方式安全地中止它们)。否则,即使在main()之后,它们也会继续运行返回并将在尝试访问内存时引发问题,因为它们不再连接到正在运行的进程。另一种可能的用途是在计算中让几个工作线程在某些检查点匹配,以便在获取下一个工作块之前共享结果

希望这能有所帮助。不过我还有一些想法,我想我会与大家分享,以防您或未来的读者不熟悉本示例中涉及的其他一些概念


您没有指出是否有一种方法可以跟踪时间并在线程之间共享时间,因此我只想给出一个快速提示:

在添加或弹出缓冲区之前锁定缓冲区。

这样做很重要,以避免一个线程试图弹出某些内容,而另一个线程正在添加并导致出现奇怪的问题,特别是如果您最终使用了诸如which sorts之类的内容并确保只有
    #include <iostream>
    #include <string>
    #include <thread>
    #include <chrono>
    #include <condition_variable>
    #include <mutex>

    bool spuriousWakeup = true;
    bool timerSet = false;
    bool terminated = false;

    int timerSeconds = 0;

    std::thread timerThread;
    std::mutex timerMutex;
    std::condition_variable timerWakeup;

    void printTimeThreadFunc()
    {
        // thread spends most of the time sleeping from condition variable
        while (!terminated){
            std::unique_lock<std::mutex> lock(timerMutex);

            if(timerSet){
                // use condition variable to sleep for time, or wake up if new time is needed
                if(timerWakeup.wait_for(lock, std::chrono::seconds(timerSeconds), []{return !spuriousWakeup;})){
                    std::cout << "setting new timer for " << timerSeconds << " seconds!" << std::endl;
                }
                else{
                    std::cout << "timer expired!" << std::endl;
                    // timer expired and there is no time to wait for
                    // so next time through we want to get the un-timed wait
                    // to wait indefinitely for a new time 
                    timerSet = false;
                }
            }
            else{
                std::cout << "waiting for timer to be set!" << std::endl;
                timerWakeup.wait(lock, []{return !spuriousWakeup;});
            }
            spuriousWakeup = true;
        }
    }

    int main()
    {
        // timer thread will exist during program execution, and will
        // be communicated with through mutex, condition variable, and flags.
        timerThread = std::thread(printTimeThreadFunc);

        while (!terminated){
            // get input from user
            std::string line; 
            std::getline(std::cin, line);

            // provide a way to quit
            if (line == "end") {
                terminated = true;
                break;
            }

            // make sure its a number
            try{
                // put scope on lock while we update variables
                {
                    std::unique_lock<std::mutex> lock(timerMutex);
                    timerSet = true;
                    timerSeconds = std::stoi(line);
                    spuriousWakeup = false;
                }
                // let thread know to process new time
                timerWakeup.notify_one();

            }
            catch (const std::invalid_argument& ia) {
                std::cerr << "Not a integer" << ia.what() << '\n';
            }
        }

        // clean up thread
        if(terminated && timerThread.joinable()){
            timerWakeup.notify_one();
            timerThread.join();
        }
    }