你如何在C++中获得sleep?

185 阅读3分钟

当一个线程在运行时,该线程有可能会停止一段时间,然后再继续运行。这就是所谓的睡眠。程序员必须决定一个线程是否需要睡眠。如果线程必须睡觉,程序员必须决定线程何时何地(在语句序列的哪个位置)必须睡觉。

下一个问题是,"什么是线程?"一个线程就像C++程序中的一个子程序。一个普通的简单C++程序就像一个线程。实际上,main()函数才是一个线程。main()函数是一个顶层函数。一个C++程序可以有其他顶层函数。其他每个顶层函数都可以正式转换成一个线程。C++的main()函数的行为就像一个线程,不需要任何形式上的转换(变成一个线程)。

C++标准命名空间有一个类似静态的类,this_thread。这个静态类有以下成员函数。

    void sleep_for(rel_time)

    void sleep_until(abs_time)

这些以 "this_thread:: "开头的函数可以在任何线程中使用,包括main()函数。main()函数不需要向线程进行任何转换。这些函数中的每一个都可以用来让一个线程休眠。这些函数中的每一个都需要一个参数。然而,参数的类型是不同的。

sleep_for()使用相对时间作为参数,而sleep_until()使用绝对时间作为参数。 rel_time,意思是相对时间,是线程睡眠的时间。另一方面,用abs_time,意思是绝对时间,对于函数sleep_until(),abs_time是线程将从睡眠中醒来的时间点。在这种情况下,当sleep_until()函数被执行时,线程开始睡觉。
C++中的Time_point是UNIX纪元之后的时间点。UNIX的纪元是1970年1月1日。

这篇文章解释了如何让线程睡觉。它首先总结了如何对线程进行编码。它还解释了如何在C++中制作一个简单的程序,sleep。

文章内容

线程编码总结

下面的程序有两个线程:其中一个是main()函数,另一个是,thread。

 #include <iostream>

    #include <thread>

    using namespace std;


    void funct() {

        cout <<"Code A goes here." <<endl;

        cout <<"Code B goes here." <<endl;

    }


    int main()

    {

        thread thr(funct);

        thr.join();


        return 0;

    }

输出的结果是:

    Code A goes here.

    Code B goes here.

该程序开始时包含了iostream库。接下来,是加入线程库,这是必须的。之后的一行是一个声明。这个声明确保程序中在它下面使用的任何名称都是标准名称空间的,除非另有说明。然后是顶级函数的定义,funct()。

在这个定义之后是main()函数。main()函数也是一个函数定义。main()函数中的第一条语句是实例化线程,thr。thr的参数是顶层函数的名称,funct()。在这个实例化中,函数funct()被调用。有效的线程是顶层函数。注意,main()函数和线程一样,没有任何关于线程的正式声明,但函数funct()有。

main()函数中的下一条语句是join()语句。这条语句必须在调用线程的函数体中出现。如果没有这条语句,main()线程可能会运行到完成,而线程本身没有完成。事实上,如果没有这条语句,g++编译器将不会编译该程序,它将发出错误信息。

相对和绝对时间对象
持续时间,间隔时间

sleep_for()函数接受一个持续时间对象作为参数。这就是相对时间。在加入chrono库后,可以按以下方式创建相对时间对象。

    chrono::hours hs(3);

    chrono::minutes ms(3);

    chrono::seconds ss(3);

    chrono::milliseconds mss(3);

    chrono::microseconds miss(3);

这里有3个小时,名称为hs;3分钟,名称为ms;3秒,名称为ss;3毫秒,名称为mss;3微秒,名称为miss。

1毫秒=1/1000秒。1微秒=1/1000000秒。

时间点

C++中的时间点(Time_point),是指UNIX纪元之后的时间点。UNIX的纪元是1970年1月1日。这就是绝对时间。函数sleep_until()使用绝对时间对象作为其参数。随着Chrono库的加入,绝对时间对象,在现在之后,可以按以下方式创建。

    chrono::system_clock::time_point tp = chrono::system_clock::now() + chrono::hours(3);

    chrono::system_clock::time_point tp = chrono::system_clock::now() + chrono::minutes(3);

    chrono::system_clock::time_point tp = chrono::system_clock::now() + chrono::seconds(3);

    chrono::system_clock::time_point tp = chrono::system_clock::now() + chrono::milliseconds(3);

    chrono::system_clock::time_point tp = chrono::system_clock::now() + chrono::microseconds(3);

这些对象的名称都是tp。

按相对时间睡眠
主要功能

要通过相对时间或持续时间进行睡眠,必须使用sleep_for()函数,前面加上 "this_thread::"。持续时间从该函数被执行时开始。main()函数是主线程,它不需要任何声明。在下面的程序中,main函数睡眠时间为1秒。

 #include <iostream>

    #include <thread>

    #include <chrono>

    using namespace std;


    int main()

    {

        cout <<"Code A goes here." <<endl;

        chrono::seconds ss(1);

        this_thread::sleep_for(ss);

        cout <<"Code B goes here." <<endl;


        return 0;

    }

输出结果是:

    Code A goes here.

并在一秒钟后。

 Code B goes here.

被显示出来。这个单线程程序没有线程声明;因为线程是main()函数。请注意,Chrono库和线程库都被包含在内。

主函数的输出是两个字符串。在这两个字符串之间,有一段代码。

    chrono::seconds ss(1);

    this_thread::sleep_for(ss);

注意睡眠函数是如何被使用的。

常规线程

对传统线程的解释,与上面的解释相似,但计时代码是在实际的线程体中。在下面的程序中,线程睡眠时间为1秒。

 #include <iostream>

    #include <thread>

    #include <chrono>

    using namespace std;


    void funct() {

        cout <<"Code A goes here." <<endl;

        chrono::seconds ss(1);

        this_thread::sleep_for(ss);

        cout <<"Code B goes here." <<endl;

    }


    int main()

    {

        thread thr(funct);

        thr.join();


        return 0;

    }

输出结果是:

  Code A goes here.

并在一秒钟后。

Code B goes here.

被显示出来。这里有两个线程:常规线程和main()函数。请注意,Chrono库和线程库都被包含在内。

在常规线程的函数主体中,有两个字符串。在这些字符串之间,有这样的代码。

    chrono::seconds ss(1);

    this_thread::sleep_for(ss);

注意这两条语句之间的关系。

按绝对时间睡眠

要通过绝对时间睡眠,必须使用sleep_until()函数,前面加上 "this_thread::" 。时间从UNIX纪元开始到未来的某个时间。如果绝对值或时间点参数是在过去,那么它将被忽略。所以,线程实际上应该在未来的时间点上被唤醒。

主函数

main()函数是主线程,它不需要任何声明。在下面的程序中,main函数睡眠到现在后1秒,时间从1970年1月1日(UNIX纪元)开始。

 #include <iostream>

    #include <thread>

    #include <chrono>

    using namespace std;


    int main()

    {

        cout <<"Code A goes here." <<endl;

        chrono::system_clock::time_point tp = chrono::system_clock::now() + chrono::seconds(1);

        this_thread::sleep_until(tp);

        cout <<"Code B goes here." <<endl;


        return 0;

    }

输出的结果是:

 Code A goes here.

并在一秒钟后。

 Code B goes here.

被显示出来。这是一个单线程程序,没有线程声明;因为线程是main()函数。请注意,Chrono库和线程库都被包含在内。

在main函数中输出了两个字符串。在这两个字符串之间,有一段代码。

chrono::system_clock::time_point tp = chrono::system_clock::now() + chrono::seconds(1);

    this_thread::sleep_until(tp);

注意睡眠函数是如何被使用的

常规线程

对传统线程的解释与上面的解释相似,但计时代码在实际的线程体中。在下面的程序中,线程一直睡到现在的1秒之后。

 #include <iostream>

    #include <thread>

    #include <chrono>

    using namespace std;


    void funct() {

        cout << "Code A goes here." <<endl;

        chrono::system_clock::time_point tp = chrono::system_clock::now() + chrono::seconds(1);

        this_thread::sleep_until(tp);

        cout << "Code B goes here." <<endl;

    }


    int main()

    {

        thread thr(funct);

        thr.join();


        return 0;

    }

输出结果是:

 Code A goes here.

并在一秒钟后。

 Code B goes here.

被显示出来。这里有两个线程:常规线程和main()函数。请注意,Chrono库和线程库都被包含在内。

在常规线程的函数主体中,输出了两个字符串。在这些字符串之间,有这样的代码。

 chrono::system_clock::time_point tp = chrono::system_clock::now() + chrono::seconds(1);

    this_thread::sleep_until(tp);

注意这两条语句之间的关系。

结论

可以让一个线程在某个时间段内睡眠,或者在UNIX纪元后的某个时间段内睡眠并唤醒。要想让线程在某个时间段内睡觉,可以使用sleep_for()函数。要想睡觉并唤醒,请使用sleep_until()函数。这些函数中的每一个都必须在前面加上这个,"this_thread::"。一个正常的简单C++程序是一个线程程序。这里的线程是main()函数,不需要线程声明。