chrono_duration(一)

news2024/11/25 20:31:07

文章目录

    • chrono简介
  • std::chrono::duration
    • duratio基本介绍
      • 基本概念
      • 使用引入
      • std::ratio 参数深入
      • 特化的duratio
        • 改造之前的代码
      • 静态成员函数 count
        • 原型
        • 例子
    • 构造函数
    • 支持加减乘除运算
      • 编译细节
    • 支持比较运算符
    • 查询范围
    • 类型转换
        • 例子引入
        • 修改seconds的范围
        • 浮点类型
        • 系统特化的duratio
        • 自定义单位转换
        • duratio源码补充
        • radio 源码补充
        • duration_cast()分析
          • 例子(重要)
          • 预定义的 radio
          • 改写例子中的代码
          • 改写例子中的代码

chrono简介

chrono是一个基于模板的,面向对象的,设计优雅且功能强大的time librarychrono内部定义了三种和时间相关的类型:

  • duration:一个duration就代表了一个时间段,比如2分钟,4小时等等。
  • clock: clock的作用就相当于我们日常使用的手表:显示时间。chrono内部定义了三种clocksystem clocksteady clockhigh-resolution-clock
  • time pointtime point表示某个特定的时间点。

std::chrono::duration

duratio基本介绍

基本概念

template<
    class Rep,
    class Period = std::ratio<1>
> class duration;

类模板 std::chrono::duration 表示时间间隔。

它由 Rep 类型的计次数和计次周期组成,其中计次周期是一个编译期有理数常量,表示从一个计次到下一个的秒数。

存储于 duration 的数据仅有 Rep 类型的计次数。若 Rep 是浮点数,则 duration 能表示小数的计次数。 Period 被包含为时长类型的一部分,且只在不同时长间转换时使用。

使用引入

例子:用 chorono 库 刻画 5s 的时间间隔

std::chrono::duration<float, std::ratio<2 / 1>> Five_Second = std::chrono::duration<float, ratio<2 / 1>>(2.5);

这里的Rep (计次数类型) 就是float, 这里的计次数 就是 2.5, 这里的 计次周期 就是 2/1 =2 s

时间间隔 = 计次数(2.5) * 计次周期(2) =5s

  • 它所表示的时间间隔和下面是等价的
std::chrono::duration<int, std::ratio<5 / 1>> Five_Second = std::chrono::duration<int, ratio<5 / 1>>(1);

这里的Rep (计次数类型) 就是int, 这里的计次数 就是 1, 这里的 计次周期 就是 5/1 =5 s

时间间隔 = 计次数(1) * 计次周期(5) =5s

std::ratio 参数深入

duration的声明包含两个模板参数,第一个模板参数是C++的原生数值类型,如long, long long等,代表了duration的数值部分。第二个模板参数_Period又是一个模板类std::ratio,它的定义如下:

template<
    std::intmax_t Num,
    std::intmax_t Denom = 1
> class ratio;
// file: ratio

namespace chrono {

    // ratio以模板的方式定义了有理数,比如ratio<1,60>就表示有理数 ‘1/60’
    // _Num代表 'numerator'(分子)
    // _Den代表 'denominator'(分母)
    template<intmax_t _Num, intmax_t _Den = 1>
    class ration {
    
        // 求__Num的绝对值
        static constexpr const intmax_t __na = __static_abs<_Num>::value;
    
        // 求_Den的绝对值
        static constexpr const intmax_t __da = __static_abs<_Den>::value;
    
        // __static_sign的作用是求符号运算
        static constexpr const intmax_t __s = __static_sign<_Num>::value * __static_sign<_Den>::value;
    
        // 求分子、分母的最大公约数
        static constexpr const intmax_t __gcd = __static_gcd<__na, __da>::value;
    
    public:
    
        // num是化简后的_Num
        static constexpr const intmax_t num = __s * __na / __gcd;
    
        // den是化简后的_Den
        static constexpr const intmax_t den = __da / __gcd;
    };
}

ratio用两个整数型模板参数来表示一个有理数的分子和分母部分,比如ratio<1, 1000>就表示有理数0.001。理解了这一点,我们再来看duration的定义:

template<class _Rep, class _Period = ratio<1> > class duration 

ratio在这里的确切含义为:以秒为单位的放大倍率,比如ratio<60, 1>表示一个1秒的60倍,也就是1分钟,而ratio<1, 1000>表示1秒的千分之一倍,也就是1毫秒。所以duration<long, ratio<60, 1>>就定义了一个类型为longduration,而这个duration的单位为“分钟”。

特化的duratio

  • chrono中宏定义了许多特例化了的duration:

    就是常见的hours,miniutes,seconds,milliseconds等,使用std::chrono::milliseconds直接使用

namespace chrono {

    // 1nano = 1/1,000,000,000 秒
    typedef ratio<1LL, 1000000000LL> nano;

    // 1micro = 1/1,000,000秒
    typedef ratio<1LL, 1000000LL> micro;

    // 1milli = 1/1,000秒
    typedef ratio<1LL, 1000LL> milli;

    // 1centi = 1/100秒
    typedef ratio<1LL, 100LL> centi;

    // 1kilo = 1,000秒
    typedef ratio<1000LL, 1LL> kilo;

    // 1mega = 1,000,000秒
    typedef ratio<1000000LL, 1LL> mega;
    
    // ...
    
    typedef duration<long long,         nano> nanoseconds;  // nanosecond是duration对象 ,nano 是 ratio对象
    typedef duration<long long,        micro> microseconds;
    typedef duration<long long,        milli> milliseconds;
    typedef duration<long long              > seconds;
    typedef duration<     long, ratio<  60> > minutes;
    typedef duration<     long, ratio<3600> > hours;
    
    // ...
}

改造之前的代码

例子:用 chorono 库 刻画 5s 的时间间隔

std::chrono::seconds Five_Second = std::chrono::seconds(5); // 这里的seconds 就是 特化的duration

静态成员函数 count

原型

constexpr rep count() const;

std::chrono::duration<Rep,Period>::count

  • 返回值

此 duration 的计次数。

例子

#include <iostream>
#include <chrono>
#include <thread>
using namespace std;
int main(int argc, char **argv)
{
    std::chrono::seconds Five_Second = std::chrono::seconds(5);
    cout << "Five_seconds的计次数为:: " << Five_Second.count() << endl;
}

Five_seconds的计次数为:: 5



构造函数

void func(std::chrono::seconds d)
{
    cout << "d的计次数为:: " << d.count() << endl;
}

int main(int argc, char **argv)
{
    // std::chrono::seconds Five_Second = std::chrono::seconds(5);
    // cout << "Five_seconds的计次数为:: " << Five_Second.count() << endl;

    // todo1  构造函数
    std::chrono::seconds Five_Second1;     // 未初始化
    std::chrono::seconds Five_Second2{};   // 零初始化
    std::chrono::seconds Five_Second3{5};  // ok 5s
    std::chrono::seconds Five_Second3(5s); // ok 5s
                                           // todo2 不允许隐式类型转换
    //  std::chrono::seconds Five_Second3 = 5; // error 不允许隐式类型转换
    //  func(5);                               // error 不允许隐式类型转换
    func(5s); // ok  5s
}

支持加减乘除运算

    void func(std::chrono::seconds d)
    {
        cout << "d的计次数为:: " << d.count() << endl;
    }
    void func2()
    {
        auto x = 3s;
        x += 2s;
        func(x);
        x = x - 5s;
        //    x+=5;//error     不能加 int 
        func(x);
    }
    // d的计次数为::5 d的计次数为::0

编译细节

比较编译器所花费时间

  • code1
std::chrono::seconds func(std::chrono::seconds d1,std::chrono::seconds d2)
{
    return d1+d2;
}
  • code 2
int64_t func(int64_t x1,int64_t x2)
{
	return x1+x2;
}

image-20230116170306752

  • 实际上他们的汇编代码是相同的,除了顶部名称修改

  • 不仅仅局限在此,下面代码的运算也是相同的

image-20230116172250075

image-20230116172316654

支持比较运算符

namespace detail2
{
    constexpr auto time_limit = 5s;
    void fun(std::chrono::seconds s)
    {
        if (s == time_limit)
        {
            cout << "equal time" << endl;
        }
        else if (s <= time_limit)
        {
            cout << "in time" << endl;
        }
        else
        {
            cout << "out of time" << endl;
        }
    }
}
 	detail2::fun(1s);
    detail2::fun(5s);
    detail2::fun(6s);
in time
equal time
out of time

查询范围

image-20230116171011768

  auto max = std::chrono::seconds::max();

    auto min = std::chrono::seconds::min();
    cout << "max = " << max.count() << endl;
    cout << "min = " << max.count() << endl;

类型转换

例子引入

  • 一般来说: 如果一个 < chrono > 转换是无损的,那么它是隐式的。如果一个转换不是无损的,它不会在没有特殊语法的情况下编译。
  • 如果转换会带来精度损失,编译就会报错。如果一定需要这样的转换,就要进行explicitly(明确的)的转换
namespace detail
{
    void func()
    {

        auto time_day = 24h;
        auto time_seconds = std::chrono::seconds(time_day);
        cout << time_seconds.count() << endl;
    }
    // void func2()
    // {

    //     auto time_seconds = 86400s;
    //     auto time_day = std::chrono::hours(time_seconds);
    //     // chrono 库不支持 将 duration(持续时间)类型从更精确的类型转换为不太精确的类型
    //     cout << time_day.count() << endl;
    // }
    void func3()
    {

        auto time_seconds = 86400s;
        auto time_day = std::chrono::duration_cast<std::chrono::hours>(time_seconds);

        cout << time_day.count() << endl;
    }
      void func4()
    {
        auto mi = std::chrono::milliseconds{3400ms};
        std::chrono::seconds s = std::chrono::duration_cast<std::chrono::seconds>(mi);
        cout << s.count() << endl;
    }

}
int main(int argc, char **argv)
{
    // 初步认识 duration_cast()强制转换

    detail::func();    // 这里没有损失精度

    // detail::func2(); // error
    detail::func3();  // 这里没有损失精度+
    
    detail::func4();  //输出 3 s ,损失精度
    
    
}

修改seconds的范围

  • 如果觉得64bit表示seconds太浪费,<chrono>还提供下面的方法,依然可以像上面的那些duration那样互转。
using seconds32 = std::chrono::duration<int32_t>;
  • 甚至下面这个也能工作:
using seconds32 = std::chrono::duration<uint32_t>;
  • 甚至下面这个也能工作(使用“safeint”库):
using seconds32 = std::chrono::duration<safe<uint32_t>>;
  • 甚至下面这个也能工作(使用浮点类型):
using fseconds = std::chrono::duration<float>;

浮点类型

对于浮点表示形式,可以从任何精度进行隐式转换,而不需要使用 period _ cast。其基本原理是没有截尾误差(只有舍入误差)。所以隐式转换是安全的。

原始的毫秒

 typedef ratio<1LL, 1000LL> milli;
 using my_ms = std::chrono::duration<double, std::milli>; // double 也可以用float代替
    void myf(my_ms d)
    {
        cout << "my_ms:: " << d.count() << " ms\n";
    };

    void f(std::chrono::milliseconds d)
    {
        cout << "f::" << d.count() << " ms\n";
    };

    void func()
    {
        // f(45ms + 63us);//原始的毫秒不支持隐式类型转换
       
        myf(45ms + 63us); // 45.063 ms
    }

系统特化的duratio

 typedef ratio<1LL, 1000000000LL> nano;

    // 1micro = 1/1,000,000秒
    typedef ratio<1LL, 1000000LL> micro;

    // 1milli = 1/1,000秒
    typedef ratio<1LL, 1000LL> milli;

    // 1centi = 1/100秒
    typedef ratio<1LL, 100LL> centi;

    // 1kilo = 1,000秒
    typedef ratio<1000LL, 1LL> kilo;

    // 1mega = 1,000,000秒
    typedef ratio<1000000LL, 1LL> mega;
typedef duration<long long, nano> nanoseconds; // 纳秒 
typedef duration<long long, micro> microseconds; // 微秒 
typedef duration<long long, milli> milliseconds; // 毫秒 
typedef duration<long long> seconds; // 秒 
typedef duration<int, ratio<60> > minutes; // 分钟 
typedef duration<int, ratio<3600> > hours; // 小时 

自定义单位转换

#include <iostream> 
#include <chrono> 
 
typedef std::chrono::duration<float, std::ratio<3, 1> > three_seconds; 
typedef std::chrono::duration<float, std::ratio<1, 10> > one_tenth_seconds; 
 
int main() 
{ 
    three_seconds s = std::chrono::duration_cast<three_seconds>(one_tenth_seconds(3)); 
    std::cout << "3 [1/10 seconds] equal to " << s.count() << " [3 seconds]\n"; 
    std::cin.get(); 
} 

duratio源码补充

std::chrono::duration是一个模板类,关键代码摘录如下(格式有调整):

template<class _Rep, class _Period> 
class duration { 
public: 
    typedef duration<_Rep, _Period> _Myt; 
    typedef _Rep rep; 
    typedef _Period period; 
     
    // constructor, save param to _MyRep, used by count() member function. 
    template<class _Rep2, 
    class = typename enable_if<is_convertible<_Rep2, _Rep>::value 
        && (treat_as_floating_point<_Rep>::value || !treat_as_floating_point<_Rep2>::value), 
        void>::type> 
    constexpr explicit duration(const _Rep2& _Val) 
        : _MyRep(static_cast<_Rep>(_Val)) 
    { 
    } 
         
    constexpr _Rep count() const { return (_MyRep);	} 
}; 
 
// convert duration from one unit to another. 
template<class _To, class _Rep, class _Period> inline 
constexpr typename enable_if<_Is_duration<_To>::value, _To>::type 
duration_cast(const duration<_Rep, _Period>& _Dur) 
{ 
typedef ratio_divide<_Period, typename _To::period> _CF; 
 
typedef typename _To::rep _ToRep; 
typedef typename common_type<_ToRep, _Rep, intmax_t>::type _CR; 
 
#pragma warning(push) 
#pragma warning(disable: 6326)	// Potential comparison of a constant with another constant. 
return (_CF::num == 1 && _CF::den == 1 
        ? static_cast<_To>(static_cast<_ToRep>(_Dur.count())) 
    : _CF::num != 1 && _CF::den == 1 
        ? static_cast<_To>(static_cast<_ToRep>( 
            static_cast<_CR>( 
                _Dur.count()) * static_cast<_CR>(_CF::num))) 
    : _CF::num == 1 && _CF::den != 1 
        ? static_cast<_To>(static_cast<_ToRep>( 
            static_cast<_CR>(_Dur.count()) 
                / static_cast<_CR>(_CF::den))) 
    : static_cast<_To>(static_cast<_ToRep>( 
        static_cast<_CR>(_Dur.count()) * static_cast<_CR>(_CF::num) 
            / static_cast<_CR>(_CF::den)))); 
#pragma warning(pop) 
} 

radio 源码补充

std::ratio是一个模板类,关键代码摘录如下(格式有调整):

template<intmax_t _Nx,	intmax_t _Dx = 1> 
struct ratio 
{ 
    static_assert(_Dx != 0,	"zero denominator"); 
    static_assert(-INTMAX_MAX <= _Nx, "numerator too negative"); 
    static_assert(-INTMAX_MAX <= _Dx, "denominator too negative"); 
 
    static constexpr intmax_t num = _Sign_of<_Nx>::value 
        * _Sign_of<_Dx>::value * _Abs<_Nx>::value / _Gcd<_Nx, _Dx>::value; 
 
    static constexpr intmax_t den = _Abs<_Dx>::value / _Gcd<_Nx, _Dx>::value; 
 
    typedef ratio<num, den> type; 
}; 

第一个参数_Nx代表了分子,第二个参数 _Dx代表了分母。
num是计算后的分子,den是计算后的分母。在duration转换的时候会用到这两个值。

注:这里的计算是指约分,可以看到传入的分子和分母都除以了最大公约数。

numnumerator的缩写,表示分子。
dendenominator的缩写,表示分母。


duration_cast()分析

  • 注明:这个函数是在duration 源码中的

函数duration_cast()提供了在不同的时间单位之间进行转换的功能。

duration_cast()主要分为两部分:

  • 通过ratio_divide定义了从一个ratio转换到另外一个ratio的转换比例。
    比如1/102/5的转换比例是1/4 ((1/10/(2/5)) = 1/4),也就是说一个1/10相当于1/42/5
    对应到代码里就是_CF::num = 1, _CF::den = 4.
  • 根据转换比例把n个单位的原数据转换到目标数据(return语句)
    return语句写的这么复杂是为了效率,避免不必要的乘除法,当分子是1的时候没必要乘,当分母是1的时候没必要除。
    简化一下(去掉了强制类型转换)就是:
    return _Dur.count() * (_CF::num / _CF::den);

通俗点讲:如果AB的转换比例是num/den,那么1A可以转换为num/denB, nA可以转换为 n * (num/den)B

例子(重要)
#include <iostream>   
#include <chrono>   
int main()  
{  
    std::chrono::milliseconds mscond(1000); // 1 second   
    std::cout << mscond.count() << " milliseconds.\n";   //1000
  
    // 时间间隔 = `计次数(count)`   * `计次周期(ration)` 
    std::cout << mscond.count() * std::chrono::milliseconds::period::num / std::chrono::milliseconds::period::den;     // 1000* 1/1000
    std::cout << " seconds.\n";  
    system("pause");  
    return 0;  
}  

这里的需要注意的是 std::chrono::milliseconds::period::numstd::chrono::milliseconds::period::den

拆开来理解:

std::chrono::milliseconds 是 duration 模板类的特化,也就是 duration类 , 在duration 类 的成员中有如下成员:

 typedef duration<_Rep, _Period> _Myt; 
    typedef _Rep rep; 
    typedef _Period period; 

所以 std::chrono::milliseconds::period 就是 引用duration中的 period成员, 接着看下面duration的类模版声明

template< 
    class Rep,
    class Period = std::ratio<1>
> class duration;

其中 period 是 _Period 类型的 ,也就是 ratio<> 类型的;所以 period 就相当于 是 ratio 类型对象 ,再结合一下ratio源码中存在两个成员 num 和 den .

就不难得出std::chrono::milliseconds::period::num / std::chrono::milliseconds::period::den 是 milliseconds (duration)的 ratio (计数周期) 也就是 1/1000 【关键】

​ 注:ratio 源码(部分)

   static constexpr intmax_t num = _Sign_of<_Nx>::value 
        * _Sign_of<_Dx>::value * _Abs<_Nx>::value / _Gcd<_Nx, _Dx>::value; 
 
    static constexpr intmax_t den = _Abs<_Dx>::value / _Gcd<_Nx, _Dx>::value; 
 
    typedef ratio<num, den> type; 

预定义的 radio

为了方便代码的书写,标准库提供了如下定义:

TypeDefinition
yoctostd::ratio<1, 1000000000000000000000000>, if std::intmax_t can represent the denominator
zeptostd::ratio<1, 1000000000000000000000>, if std::intmax_t can represent the denominator
attostd::ratio<1, 1000000000000000000>
femtostd::ratio<1, 1000000000000000>
picostd::ratio<1, 1000000000000>
nanostd::ratio<1, 1000000000>
microstd::ratio<1, 1000000>
millistd::ratio<1, 1000>
centistd::ratio<1, 100>
decistd::ratio<1, 10>
decastd::ratio<10, 1>
hectostd::ratio<100, 1>
kilostd::ratio<1000, 1>
megastd::ratio<1000000, 1>
gigastd::ratio<1000000000, 1>
terastd::ratio<1000000000000, 1>
petastd::ratio<1000000000000000, 1>
exastd::ratio<1000000000000000000, 1>
zettastd::ratio<1000000000000000000000, 1>, if std::intmax_t can represent the numerator
yottastd::ratio<1000000000000000000000000, 1>, if std::intmax_t can represent the numerator
改写例子中的代码

结合预定义的radio

#include <iostream>
#include <chrono>
using namespace std;
int main()
{
    std::chrono::milliseconds mscond(1000);            // 1000ms
    std::cout << mscond.count() << " milliseconds.\n"; // 1000

    // 时间间隔 = `计次数(count)`   * `计次周期(ration)`
    std::milli mi;

    std::cout << mscond.count() * mi.num / mi.den; // 1000* 1/1000
    // cout << "mi.num" << mi.num << "mi.den" << mi.den << endl;

    std::cout
        << " seconds.\n";

    return 0;
}
               |

| zetta | std::ratio<1000000000000000000000, 1>, if std::intmax_t can represent the numerator |
| yotta | std::ratio<1000000000000000000000000, 1>, if std::intmax_t can represent the numerator |

改写例子中的代码

结合预定义的radio

#include <iostream>
#include <chrono>
using namespace std;
int main()
{
    std::chrono::milliseconds mscond(1000);            // 1000ms
    std::cout << mscond.count() << " milliseconds.\n"; // 1000

    // 时间间隔 = `计次数(count)`   * `计次周期(ration)`
    std::milli mi;

    std::cout << mscond.count() * mi.num / mi.den; // 1000* 1/1000
    // cout << "mi.num" << mi.num << "mi.den" << mi.den << endl;

    std::cout
        << " seconds.\n";

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/167985.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

os模块的使用方法详解

os模块os模块负责程序与操作系统的交互&#xff0c;提供了访问操作系统底层的接口&#xff1b;即os模块提供了非常丰富的方法用来处理文件和目录。使用的时候需要导入该模块&#xff1a;import os常用方法如下&#xff1a;方法名作用os.remove(‘path/filename’)删除文件os.re…

Unidbg模拟执行某段子so实操教程(一) 先把框架搭起来

一、目标 最近又开始研究Unidbg了&#xff0c;费了好大劲&#xff0c;没有跑起来。今天就先找个软柿子捏捏看。 今天的目标是 之前研究的 某段子App签名计算方法(一) 某段子App版本 5.5.10 二、步骤 先搭起框架来 在 /unidbg/unidbg-android/src/test/java/ 下面新建一个 …

K8S 三种探针ReadinessProbe、LivenessProbe和StartupProbe 之探索

一、事件背景因为k8s中采用大量的异步机制&#xff0c;以及多种对象关系设计上的解耦&#xff0c;当应用实例数增加/删除、或者应用版本发生变化触发滚动升级时&#xff0c;系统并不能保证应用相关的service、ingress配置总是及时能完成刷新。在一些情况下&#xff0c;往往只是…

Python爬虫之Scrapy框架系列(4)——项目实战【某瓣Top250电影更多信息的获取】

前言&#xff1a; 上篇文章使用Scrapy框架简单爬取并下载了某瓣Top250首页的排名前25个电影的电影名。 太寒酸了&#xff0c;这篇文章咱就来仔细搞一搞&#xff0c;搞到更加详细的信息&#xff01;&#xff01;&#xff01; 目录&#xff1a;1.分析2.使用scrapy shell提取电影详…

进程信号--Linux

文章目录信号&#xff1f;kill -l 指令查看所有信号信号的工作流程信号产生1.通过终端按键产生信号2.通过系统调用接口产生信号3.通过软件产生信号4.硬件异常产生信号信号接收信号处理总结信号&#xff1f; 进程间的通信我们了解到有管道通信&#xff0c;有共享内存的通信。这…

flowable编译

git clone -b flowable-release-6.7.2 https://github.com/flowable/flowable-engine.git下载之后File-Open&#xff0c;打开工程&#xff0c;modules是核心代码模块 找到flowable-root.xml按下altf12 &#xff0c;启动Terminal终端输入命令&#xff1a;mvn clean package -Ds…

《Buildozer打包实战指南》第三节 安装Buildozer打包所需的依赖文件

目录 3.1 安装依赖软件包 3.2 安装Cython 3.3 设置环境变量 3.4 安装p4a、Android SDK、NDK以及其他编译文件 Buidozer这个打包库下载安装完毕之后&#xff0c;我们还需要下载一些打包安卓apk所需要的依赖文件。 3.1 安装依赖软件包 首先输入以下命令更新Ubuntu上的软件包…

使众人行:如何带领一群人把事做成?

你好&#xff0c;我是雷蓓蓓&#xff0c;一名程序员出身的项目经理&#xff0c;曾任网易杭研项目管理部总监。 我所带领的网易杭研项目管理部&#xff0c;从2011年成立以来&#xff0c;就一直在互联网项目管理领域深耕&#xff0c;为网易云音乐、网易严选、云计算、智慧企业等…

智慧社区管理系统改造方案

伴随着城市发展的持续加速&#xff0c;许多在建智慧社区和老旧小区智能化改造都在有规划的展开着。如今许多老旧小区在展开设备升级&#xff0c;许多小区智能安防设备、物业管理服务系统软件、社区综合服务平台及其监控器设备等都会展开智能化改造。但是&#xff0c;很多人对老…

17.优于select的epoll

优于select的epoll epoll 理解及应用 select复用方法其实由来已久&#xff0c;因此&#xff0c;利用该技术后&#xff0c;无论如何优化程序性能也无法同时接入上百个客户端&#xff08;当然&#xff0c;硬件性能不同&#xff0c;差别也很大&#xff09;。这种select方式并不适…

IIC驱动中景园0.96寸OLED

驱动硬件介绍 1、驱动电压3.3到5,但是正点的也是这个芯片说用3.3 5会烧坏掉。 2、RST 上的低电平,将导致OLED 复位,在每次初始化之前,都应该复位一下 OLED 模块。而我们使用四线,里面就没有复位了 3、裸屏有多种接口方式(驱动芯片为SSD1306) 6800、8080 两种并行接口方…

Redis应用2(Redison)

不推荐使用application的配置方式,因为会替代spring内部的对于redis的配置方式 注意:如果redis数据库没有密码,不要使用 config.useSingleServer().setPassword("") 的形式,直接跳过setPassword()就可以,配置类写法如下: Configuration public class RedisConfig…

MySQL进阶——索引

一、索引及其分类 1.索引的概念 索引是一种特殊的文件&#xff0c;包含着对数据表中所有记录的引用指针通俗点说&#xff0c;索引就好比是一本书的目录&#xff0c;能加快数据库的查询速度例如需要遍历 200 条数据&#xff0c;在没有索引的情况下&#xff0c;数据库会遍历全部…

Spring之事务编程概述

目录 一&#xff1a;基本概念 搭建测试环境 基于xml声明式事务控制 二&#xff1a;事务相关配置 ​编辑 基于注解声明式事务控制 三&#xff1a;Spring事务角色 四&#xff1a;事务传播行为 五&#xff1a;案例&#xff1a;转账业务追加日志 一&#xff1a;基本概念 事…

Vue.nextTick核心原理

相信大家在写vue项目的时候&#xff0c;一定会发现一个神奇的api&#xff0c;Vue.nextTick。为什么说它神奇呢&#xff0c;那是因为在你做某些操作不生效时&#xff0c;将操作写在Vue.nextTick内&#xff0c;就神奇的生效了。那这是什么原因呢&#xff1f; 让我们一起来研究一…

手把手教你写Dockerfile以及测试

Dockerfile是什么&#xff1f; dockerfile就是用来构建docker镜像的构建文件,命令参数脚本。 如何使用Dockerfile&#xff1f; 1、编写一个Dockerfile文件2、docker build构建成 基础使用&#xff08;此处罗列一些我们经常用到的&#xff09; # 指定依赖镜像版本&#xff…

【附代码】十大主流聚类算法

准备工作安装必要的库pip install scikit-learn准备数据集使用 make _ classification ()函数创建一个测试二分类数据集。数据集将有1000个示例&#xff0c;每个类有两个输入要素和一个群集。这些群集在两个维度上是可见的&#xff0c;因此我们可以用散点图绘制数据&#xff0c…

第18章_JDBC

一、JDBC概述JDBC概述什么是JDBCJDBC&#xff08;Java DataBase Connectivity, Java数据库连接&#xff09; ,是一种用于执行SQL语句的Java API&#xff0c;为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成有了JDBC&#xff0c;程序员只需用JDBC API写一个…

夜深忽梦少年事,7年又一年,来看看95年那个小伙现在怎么样了

2022年已到尾声&#xff0c;疫情也结束了&#xff0c;这三年太不容易了&#xff0c;今年也是一样在疫情的艰难的度过&#xff0c;就是做了两件事&#xff0c;防疫和上班&#xff0c;没什么可写的。但是在一个深夜晚上&#xff0c;想了很多以前的事&#xff0c;想想还是写一点东…

亚马逊云科技Amazon DeepRacer互联网行业全国冠军诞生

1月11日&#xff0c;首届亚马逊云科技Amazon DeepRacer自动驾驶赛车互联网行业全国总决赛圆满结束&#xff0c;从全国各地选拔出的9支冠军队伍齐聚滨海三亚&#xff0c;向总决赛的桂冠发起了冲击。 本次比赛沿袭了Amazon DeepRacer League全球赛事标准&#xff0c;使用了全新的…