【研发日记】Matlab/Simulink软件优化(二)——通信负载柔性均衡算法

文章目录


前言

背景介绍

初始代码

优化代码

分析和应用

总结


前言

        见《【研发日记】Matlab/Simulink软件优化(一)——动态内存负荷压缩》

背景介绍

        在一个嵌入式软件开发项目中,需要设计一个ECU节点的CAN网路数据发送,需求是在500k的通信波特率上,动态发送10到40帧报文,发送一轮的时间最长不能超过50ms。示例如下:

初始代码

        一开始算法开发的思路非常简单,就是设置一个50ms的任务,用for循环把要发送的数据装入CAN发送Buffer。示例如下:

        以上模型生成的代码如下:


#include "untitled.h"
#include "untitled_private.h"

/* Block signals (default storage) */
B_untitled_T untitled_B;

/* Block states (default storage) */
DW_untitled_T untitled_DW;

/* Real-time model */
static RT_MODEL_untitled_T untitled_M_;
RT_MODEL_untitled_T *const untitled_M = &untitled_M_;

/* Model step function */
void untitled_step(void)
{
  int32_T i;
  int32_T rtb_Gain;
  int32_T s6_iter;
  char_T *sErr;
  void *inputMsgRef;

  /* Outputs for Enabled SubSystem: '<Root>/Subsystem' incorporates:
   *  EnablePort: '<S3>/Enable'
   */
  /* RelationalOperator: '<S1>/Compare' incorporates:
   *  Constant: '<S1>/Constant'
   *  UnitDelay: '<S2>/Output'
   */
  if (untitled_DW.Output_DSTATE == 0) {
    if (!untitled_DW.Subsystem_MODE) {
      /* Enable for Iterator SubSystem: '<S3>/For Iterator Subsystem' */
      /* Enable for S-Function (svntcantransmit): '<S6>/CAN Transmit' */
      sErr = GetErrorBuffer(&untitled_DW.CANTransmit_CANTransmit[0U]);
      LibReset(&untitled_DW.CANTransmit_CANTransmit[0U]);
      LibStart(&untitled_DW.CANTransmit_CANTransmit[0U]);
      if (*sErr != 0) {
        rtmSetErrorStatus(untitled_M, sErr);
        rtmSetStopRequested(untitled_M, 1);
      }

      /* End of Enable for S-Function (svntcantransmit): '<S6>/CAN Transmit' */
      /* End of Enable for SubSystem: '<S3>/For Iterator Subsystem' */
      untitled_DW.Subsystem_MODE = true;
    }

    /* Outputs for Iterator SubSystem: '<S3>/For Iterator Subsystem' incorporates:
     *  ForIterator: '<S6>/For Iterator'
     */
    for (s6_iter = 0; s6_iter < 40; s6_iter++) {
      /* Gain: '<S6>/Gain' */
      rtb_Gain = s6_iter << 3;
      for (i = 0; i < 8; i++) {
        /* Selector: '<S6>/Selector' incorporates:
         *  Constant: '<Root>/Constant'
         */
        untitled_B.Selector[i] = untitled_ConstP.Constant_Value[i + rtb_Gain];
      }

      /* S-Function (scanpack): '<S6>/CAN Pack' */
      /* S-Function (scanpack): '<S6>/CAN Pack' */
      untitled_B.CANPack.ID = 10U;
      untitled_B.CANPack.Length = 8U;
      untitled_B.CANPack.Extended = 0U;
      untitled_B.CANPack.Remote = 0;
      untitled_B.CANPack.Data[0] = 0;
      untitled_B.CANPack.Data[1] = 0;
      untitled_B.CANPack.Data[2] = 0;
      untitled_B.CANPack.Data[3] = 0;
      untitled_B.CANPack.Data[4] = 0;
      untitled_B.CANPack.Data[5] = 0;
      untitled_B.CANPack.Data[6] = 0;
      untitled_B.CANPack.Data[7] = 0;

      {
        (void) memcpy((untitled_B.CANPack.Data), &untitled_B.Selector[0],
                      8 * sizeof(uint8_T));
      }

      /* S-Function (svntcantransmit): '<S6>/CAN Transmit' */
      sErr = GetErrorBuffer(&untitled_DW.CANTransmit_CANTransmit[0U]);

      /* S-Function (scanpack): '<S6>/CAN Pack' incorporates:
       *  S-Function (svntcantransmit): '<S6>/CAN Transmit'
       */
      inputMsgRef = &untitled_B.CANPack;

      /* S-Function (svntcantransmit): '<S6>/CAN Transmit' */
      LibOutputs_CANTransmit(&untitled_DW.CANTransmit_CANTransmit[0U],
        inputMsgRef, 1);
      if (*sErr != 0) {
        rtmSetErrorStatus(untitled_M, sErr);
        rtmSetStopRequested(untitled_M, 1);
      }
    }

    /* End of Outputs for SubSystem: '<S3>/For Iterator Subsystem' */
  } else {
    if (untitled_DW.Subsystem_MODE) {
      /* Disable for Iterator SubSystem: '<S3>/For Iterator Subsystem' */
      /* Disable for S-Function (svntcantransmit): '<S6>/CAN Transmit' */
      sErr = GetErrorBuffer(&untitled_DW.CANTransmit_CANTransmit[0U]);
      LibReset(&untitled_DW.CANTransmit_CANTransmit[0U]);
      if (*sErr != 0) {
        rtmSetErrorStatus(untitled_M, sErr);
        rtmSetStopRequested(untitled_M, 1);
      }

      /* End of Disable for S-Function (svntcantransmit): '<S6>/CAN Transmit' */
      /* End of Disable for SubSystem: '<S3>/For Iterator Subsystem' */
      untitled_DW.Subsystem_MODE = false;
    }
  }

  /* End of RelationalOperator: '<S1>/Compare' */
  /* End of Outputs for SubSystem: '<Root>/Subsystem' */

  /* Switch: '<S5>/FixPt Switch' incorporates:
   *  Constant: '<S4>/FixPt Constant'
   *  Constant: '<S5>/Constant'
   *  Sum: '<S4>/FixPt Sum1'
   *  UnitDelay: '<S2>/Output'
   */
  if ((uint8_T)(untitled_DW.Output_DSTATE + 1U) > 49) {
    untitled_DW.Output_DSTATE = 0U;
  } else {
    untitled_DW.Output_DSTATE++;
  }

  /* End of Switch: '<S5>/FixPt Switch' */
}

/* Model initialize function */
void untitled_initialize(void)
{
  {
    int32_T bitParams[4];
    char_T *sErr;

    /* Start for S-Function (svntcantransmit): '<S6>/CAN Transmit' */
    sErr = GetErrorBuffer(&untitled_DW.CANTransmit_CANTransmit[0U]);
    CreateHostLibrary("slhostlibcantransmit.dll",
                      &untitled_DW.CANTransmit_CANTransmit[0U]);
    if (*sErr == 0) {
      bitParams[0U] = 1;
      bitParams[1U] = 4;
      bitParams[2U] = 3;
      bitParams[3U] = 1;
      LibCreate_CANTransmit(&untitled_DW.CANTransmit_CANTransmit[0U], "vector",
                            "slvectorxlwrapper.dll", "Virtual", 0, 1, 1, 1,
                            "canslconverter", "vectorxlplugin", 500000.0,
                            &bitParams[0U], 0, 0, 0, 1.0, 0);
    }

    if (*sErr == 0) {
      LibStart(&untitled_DW.CANTransmit_CANTransmit[0U]);
    }

    if (*sErr != 0) {
      rtmSetErrorStatus(untitled_M, sErr);
      rtmSetStopRequested(untitled_M, 1);
    }

    /* End of Start for S-Function (svntcantransmit): '<S6>/CAN Transmit' */
    /* End of SystemInitialize for SubSystem: '<S3>/For Iterator Subsystem' */
    /* End of SystemInitialize for SubSystem: '<Root>/Subsystem' */
  }
}

/* Model terminate function */
void untitled_terminate(void)
{
  char_T *sErr;

  /* Terminate for Enabled SubSystem: '<Root>/Subsystem' */
  /* Terminate for Iterator SubSystem: '<S3>/For Iterator Subsystem' */
  /* Terminate for S-Function (svntcantransmit): '<S6>/CAN Transmit' */
  sErr = GetErrorBuffer(&untitled_DW.CANTransmit_CANTransmit[0U]);
  LibTerminate(&untitled_DW.CANTransmit_CANTransmit[0U]);
  if (*sErr != 0) {
    rtmSetErrorStatus(untitled_M, sErr);
    rtmSetStopRequested(untitled_M, 1);
  }

  LibDestroy(&untitled_DW.CANTransmit_CANTransmit[0U], 0);
  DestroyHostLibrary(&untitled_DW.CANTransmit_CANTransmit[0U]);

  /* End of Terminate for S-Function (svntcantransmit): '<S6>/CAN Transmit' */
  /* End of Terminate for SubSystem: '<S3>/For Iterator Subsystem' */
  /* End of Terminate for SubSystem: '<Root>/Subsystem' */
}

        按照上述示例生成的代码,调试时监测到CAN网络上的瞬时负载率,在0%和100%之间来回跳变。0%和100%各自占用一段时间,两者的比例随着发送报文数量的多少变化。当报文数为最大的40帧时,100%瞬时负载率会持续10ms左右,如下图所示:

        分析上述网络通信的特点,100%瞬时负载率持续的10ms时间段里,肯定会有其他ECU节点也发出报文,这时候CAN网络就会自动根据ID的优先级分配谁先发,谁等待后发,即出现冲突抢占现象。在CAN网络中如果冲突抢占是偶发的,那就不会有太大影响,但是如果冲突抢占是持续的,那就不是我们希望看到的了。

优化代码

        根据对上述问题的分析,我们发现每个50ms周期里边都还有至少40ms是没有利用的,那么只要把前面拥挤的报文分散开到后面一部分,就能解决前面的问题了。然后如果还有剩余的时间没有利用,那么我们就柔性地缩短50ms的周期时长,提高数据发送的频率。这样既能解决前面的问题,又能把总线资源充分利用起来,用于提高我们网络通信的性能。示例如下:

        以上模型生成的代码如下:

#include "untitled.h"
#include "untitled_private.h"

/* Named constants for Chart: '<S1>/Chart' */
#define untitled_IN_a                  ((uint8_T)1U)
#define untitled_IN_a1                 ((uint8_T)2U)

/* Block signals (default storage) */
B_untitled_T untitled_B;

/* Block states (default storage) */
DW_untitled_T untitled_DW;

/* Real-time model */
static RT_MODEL_untitled_T untitled_M_;
RT_MODEL_untitled_T *const untitled_M = &untitled_M_;

/* Model step function */
void untitled_step(void)
{
  real_T rtb_Gain;
  int32_T i;
  char_T *sErr;
  void *inputMsgRef;

  /* Chart: '<S1>/Chart' incorporates:
   *  Constant: '<Root>/Constant3'
   */
  if (untitled_DW.is_active_c3_untitled == 0U) {
    untitled_DW.is_active_c3_untitled = 1U;
    untitled_DW.is_c3_untitled = untitled_IN_a;
    untitled_B.FrameIndex = 0.0;
  } else if (untitled_DW.is_c3_untitled == untitled_IN_a) {
    untitled_DW.is_c3_untitled = untitled_IN_a1;
    untitled_B.FrameIndex++;
  } else {
    /* case IN_a1: */
    if (untitled_B.FrameIndex >= 39.0) {
      untitled_DW.is_c3_untitled = untitled_IN_a;
      untitled_B.FrameIndex = 0.0;
    }
  }

  /* End of Chart: '<S1>/Chart' */

  /* Gain: '<S1>/Gain' */
  rtb_Gain = 8.0 * untitled_B.FrameIndex;
  for (i = 0; i < 8; i++) {
    /* Selector: '<S1>/Selector' incorporates:
     *  Constant: '<Root>/Constant2'
     */
    untitled_B.Selector[i] = untitled_ConstP.Constant2_Value[i + (int32_T)
      rtb_Gain];
  }

  /* S-Function (scanpack): '<S1>/CAN Pack' */
  /* S-Function (scanpack): '<S1>/CAN Pack' */
  untitled_B.CANPack.ID = 10U;
  untitled_B.CANPack.Length = 8U;
  untitled_B.CANPack.Extended = 0U;
  untitled_B.CANPack.Remote = 0;
  untitled_B.CANPack.Data[0] = 0;
  untitled_B.CANPack.Data[1] = 0;
  untitled_B.CANPack.Data[2] = 0;
  untitled_B.CANPack.Data[3] = 0;
  untitled_B.CANPack.Data[4] = 0;
  untitled_B.CANPack.Data[5] = 0;
  untitled_B.CANPack.Data[6] = 0;
  untitled_B.CANPack.Data[7] = 0;

  {
    (void) memcpy((untitled_B.CANPack.Data), &untitled_B.Selector[0],
                  8 * sizeof(uint8_T));
  }

  /* S-Function (svntcantransmit): '<S1>/CAN Transmit' */
  sErr = GetErrorBuffer(&untitled_DW.CANTransmit_CANTransmit[0U]);

  /* S-Function (scanpack): '<S1>/CAN Pack' incorporates:
   *  S-Function (svntcantransmit): '<S1>/CAN Transmit'
   */
  inputMsgRef = &untitled_B.CANPack;

  /* S-Function (svntcantransmit): '<S1>/CAN Transmit' */
  LibOutputs_CANTransmit(&untitled_DW.CANTransmit_CANTransmit[0U], inputMsgRef,
    1);
  if (*sErr != 0) {
    rtmSetErrorStatus(untitled_M, sErr);
    rtmSetStopRequested(untitled_M, 1);
  }
}

/* Model initialize function */
void untitled_initialize(void)
{
  {
    int32_T bitParams[4];
    char_T *sErr;

    /* Start for S-Function (svntcantransmit): '<S1>/CAN Transmit' */
    sErr = GetErrorBuffer(&untitled_DW.CANTransmit_CANTransmit[0U]);
    CreateHostLibrary("slhostlibcantransmit.dll",
                      &untitled_DW.CANTransmit_CANTransmit[0U]);
    if (*sErr == 0) {
      bitParams[0U] = 1;
      bitParams[1U] = 4;
      bitParams[2U] = 3;
      bitParams[3U] = 1;
      LibCreate_CANTransmit(&untitled_DW.CANTransmit_CANTransmit[0U], "vector",
                            "slvectorxlwrapper.dll", "Virtual", 0, 1, 1, 1,
                            "canslconverter", "vectorxlplugin", 500000.0,
                            &bitParams[0U], 0, 0, 0, 1.0, 0);
    }

    if (*sErr == 0) {
      LibStart(&untitled_DW.CANTransmit_CANTransmit[0U]);
    }

    if (*sErr != 0) {
      rtmSetErrorStatus(untitled_M, sErr);
      rtmSetStopRequested(untitled_M, 1);
    }

    /* End of Start for S-Function (svntcantransmit): '<S1>/CAN Transmit' */

    /* Enable for S-Function (svntcantransmit): '<S1>/CAN Transmit' */
    sErr = GetErrorBuffer(&untitled_DW.CANTransmit_CANTransmit[0U]);
    LibReset(&untitled_DW.CANTransmit_CANTransmit[0U]);
    LibStart(&untitled_DW.CANTransmit_CANTransmit[0U]);
    if (*sErr != 0) {
      rtmSetErrorStatus(untitled_M, sErr);
      rtmSetStopRequested(untitled_M, 1);
    }

    /* End of Enable for S-Function (svntcantransmit): '<S1>/CAN Transmit' */
  }
}

/* Model terminate function */
void untitled_terminate(void)
{
  char_T *sErr;

  /* Terminate for S-Function (svntcantransmit): '<S1>/CAN Transmit' */
  sErr = GetErrorBuffer(&untitled_DW.CANTransmit_CANTransmit[0U]);
  LibTerminate(&untitled_DW.CANTransmit_CANTransmit[0U]);
  if (*sErr != 0) {
    rtmSetErrorStatus(untitled_M, sErr);
    rtmSetStopRequested(untitled_M, 1);
  }

  LibDestroy(&untitled_DW.CANTransmit_CANTransmit[0U], 0);
  DestroyHostLibrary(&untitled_DW.CANTransmit_CANTransmit[0U]);

  /* End of Terminate for S-Function (svntcantransmit): '<S1>/CAN Transmit' */
}

        按照上述示例生成的代码,调试时监测到CAN网络上的瞬时负载率非常均匀地保持在25%左右。并且不管报文数量的如何变化,软件都能自动地柔性处理,既不会负载率过高,也不会总线资源浪费,同时又能将报文频率性能发挥到最大。如下图所示:

        分析上述网络通信的特点,已实现了项目中的需求,同时也利用通信负载柔性均衡算法把性能发挥到了最优。

分析和应用

        通信负载均衡,在不同的软件开发项目中重要性是不一样的。一种是实时性要求高的的应用(例如底盘控制),每一帧消息都要在准确的时间发送出去,不允许冲突抢占导致的延误。另一种是网络通信资源非常小的总线(例如低速CAN),单位时间内能发送的报文数量本来就比较少,所以更要仔细计算充分利用,要不然很容易因为负载不均衡导致报文阻塞。

        使用通信负载柔性均衡算法时,需要注意如下几点:

        1、不同波特率,理想负载率下,单位时间对应的报文数量需要仔细的计算,才能设定出最优的算法。例如:500k波特率,在25%理想负载率下,1ms对应的报文数量就是1帧。同理如果1M波特率,那么1ms对应的报文数量就是2帧。

        2、计算好最优的理论算法之后,还要更具自己处理器的性能,设定一个合适的控制粒度。例如:自己的软件最快可以1ms运算一圈,那么就可以1ms控制一次发送1帧或者2帧。如果自己的软件最快只能5ms运算一圈,那么同理就5ms控制一次发送5帧或者10帧。这里的控制粒度越小,负载均衡的效果也越好,但是并非所有的平台都能达到理论极限,只要在自己平台的基础上发挥到最优即可。

        3、对于有网络管理机制的应用场景,需求方可能不希望我们的50ms周期发生变化。例如,网络上的主ECU节点利用同步信号,控制着各个从ECU节点分别占用这50ms中的一小段。当我们自己节点的报文发送完之后,需要等着下一个50ms的到来,或者下一个同步信号的到来。这时候就要把FrameIndex的循环Limit固定成50ms,然后在Transmit模块上加一个使能条件FrameIndex < FrameNum。这样也能达到我们通信负载柔性均衡的目的,同时也满足主ECU节点的网络管理。

总结

        以上就是本人在嵌入式软件开发中处理通信负载率不均衡问题时,一些个人理解和分析的总结,首先介绍了它的背景情况,然后展示它的初始设计和优化设计,最后分析了通信负载均衡算法的注意事项和应用场景。

        后续还会分享另外几个最近总结的软件优化知识点,欢迎评论区留言、点赞、收藏和关注,这些鼓励和支持都将成文本人持续分享的动力。

        另外,上述例程使用的Demo工程,可以到笔者的主页查找和下载。


        版权声明:原创文章,转载和引用请注明出处和链接,侵权必究

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python logging 模块详解

Python 的 logging 模块提供了一个强大而灵活的日志系统。它是 Python 标准库的一部分&#xff0c;因此可以在任何 Python 程序中使用。logging 模块提供了许多有用的功能&#xff0c;包括日志消息的级别设置、日志消息的格式设置、将日志消息输出到不同的目标&#xff0c;以及…

Mysql8安装教程与配置(超详细图文)

MySQL 8.0 是 MySQL 数据库的一个重大更新版本&#xff0c;它引入了许多新特性和改进&#xff0c;旨在提高性能、安全性和易用性。 1.下载MySQL 安装包 注&#xff1a;本文使用的是压缩版进行安装。 &#xff08;1&#xff09;从网盘下载安装文件 点击此处直接下载 &#…

Android 开机动画的启动过程BootAnimation(基于Android10.0.0-r41)

文章目录 Android 开机动画的启动过程BootAnimation(基于Android10.0.0-r41)1.开机动画的启动过程概述2.为什么设置了属性之后就会播放&#xff1f; Android 开机动画的启动过程BootAnimation(基于Android10.0.0-r41) 1.开机动画的启动过程概述 下面就是BootAnimation的重要部…

KIBANA的安装教程(超详细)

前言 Kibana 是一个开源的基于浏览器的可视化工具&#xff0c;主要用于分析和展示存储在 Elasticsearch 索引中的数据。它允许用户通过各种图表、地图和其他可视化形式来探索和理解大量数据。Kibana 与 Elasticsearch 和 Logstash 紧密集成&#xff0c;共同构成了所谓的 ELK 堆…

【论文阅读】SELF-RAG,让模型决策和反思检索

关于LLM何时使用RAG的问题&#xff0c;原本是阅读了关于ADAPT-LLM模型的那篇论文&#xff0c;被问到与SELF-RAG有何区别。所以&#xff0c;大概看了一下SELF-RAG这篇论文&#xff0c;确实很像&#xff0c;这些基于LLM针对下游任务的模型架构和方法&#xff0c;本来就很像。不过…

[AVL数四种旋转详细图解]

文章目录 一.右单旋二. 左单旋三. 右左双旋四. 左右双旋 一.右单旋 新节点插入较高左子树的左侧—左左&#xff1a;右单旋 由于在较高左子树的左侧插入一个节点后&#xff0c;左边插入导致30的平衡因子更新为-1&#xff0c;而60平衡因子更新为-2&#xff0c;此时不平衡&…

oracle数据库通过impdp导入数据时提示,ORA-31684:对象类型用户xxx已存在,和ORA-39151:表xxx存在的解决办法

前提条件&#xff1a;首先备份原数据库中此用户对应的schemas 比如名为cams_wf的schemas 以便出了问题后还可以恢复原数据。 解决办法一、 通过命令或者数据库管理工具删除掉此schemas下的所有表&#xff0c;然后在impdp中加入ignorey 来忽略ORA-31684&#xff1a;对象类型用…

Signac|成年小鼠大脑 单细胞ATAC分析(1)

引言 在本教程中&#xff0c;我们将探讨由10x Genomics公司提供的成年小鼠大脑细胞的单细胞ATAC-seq数据集。本教程中使用的所有相关文件均可在10x Genomics官方网站上获取。 本教程复现了之前在人类外周血单核细胞&#xff08;PBMC&#xff09;的Signac入门教程中执行的命令。…

Spring运维之boot项目bean属性的绑定读取与校验

第三方bean属性的绑定 先写一个实体类 我们在配置yml文件里写了属性值 能一一对应 我们用注解让其对应 我们在启动类里面测试 我们首先拿到容器对象 再拿到bean 打印bean 发现我们的容器获取到的bean bean的属性与配置里面的属性一一对应 这时候提出一个问题 这是我们自定义…

C++设计模式-外观模式,游戏引擎管理多个子系统,反汇编

运行在VS2022&#xff0c;x86&#xff0c;Debug下。 30. 外观模式 为子系统定义一组统一的接口&#xff0c;这个高级接口会让子系统更容易被使用。应用&#xff1a;如在游戏开发中&#xff0c;游戏引擎包含多个子系统&#xff0c;如物理、渲染、粒子、UI、音频等。可以使用外观…

组态软件远程监控

在信息化、智能化的浪潮下&#xff0c;远程监控技术已经渗透到工业生产的各个领域。HiWoo Cloud平台凭借其卓越的组态软件远程监控功能&#xff0c;为企业提供了高效、智能的监控解决方案&#xff0c;推动了工业生产的数字化转型。本文将详细介绍HiWoo Cloud平台在组态软件远程…

【机器学习】GLM4-9B-Chat大模型/GLM-4V-9B多模态大模型概述、原理及推理实战

​​​​​​​ 目录 一、引言 二、模型简介 2.1 GLM4-9B 模型概述 2.2 GLM4-9B 模型架构 三、模型推理 3.1 GLM4-9B-Chat 语言模型 3.1.1 model.generate 3.1.2 model.chat 3.2 GLM-4V-9B 多模态模型 3.2.1 多模态模型概述 3.2.2 多模态模型实践 四、总结 一、引言…

cocos入门4:项目目录结构

Cocos Creator 项目结构教程 Cocos Creator 是一个功能强大的游戏开发工具&#xff0c;它为开发者提供了直观易用的界面和强大的功能来快速创建游戏。在使用 Cocos Creator 开发游戏时&#xff0c;合理地组织项目结构对于项目的可维护性和扩展性至关重要。以下是一个关于如何设…

49.线程池的关闭方法

shutdown方法 1.线程池状态变为shutdown 2.不会接收新任务 3.已提交的任务会执行完 4.此方法不会阻塞调用线程执行 ExecutorService executorService = Executors.newFixedThreadPool(2);executorService.submit(() -> {log.debug("task1 running");try {TimeUnit…

可视化数据科学平台在信贷领域应用系列五:零代码可视化建模

信贷风控模型是金融机构风险管理的核心工具&#xff0c;在信贷风险管理工作中扮演着至关重要的角色。随着信贷市场的环境不断变化&#xff0c;信贷业务的风险日趋复杂化和隐蔽化&#xff0c;开发和应用准确高效的信贷风控模型显得尤为重要。信贷风险控制面临着越来越大的挑战和…

Go实战 | 使用Go-Fiber采用分层架构搭建一个简单的Web服务

前言 &#x1f4e2;博客主页&#xff1a;程序源⠀-CSDN博客 &#x1f4e2;欢迎点赞&#x1f44d;收藏⭐留言&#x1f4dd;如有错误敬请指正&#xff01; 一、环境准备、示例介绍 Go语言安装&#xff0c;GoLand编辑器 这个示例实现了一个简单的待办事项&#xff08;todo&#xf…

【Linux网络】传输层协议 - UDP

文章目录 一、传输层&#xff08;运输层&#xff09;运输层的特点复用和分用再谈端口号端口号范围划分认识知名端口号&#xff08;Well-Know Port Number&#xff09;两个问题① 一个进程是否可以绑定多个端口号&#xff1f;② 一个端口号是否可以被多个进程绑定&#xff1f; n…

暗黑系短视频:成都鼎茂宏升文化传媒公司

暗黑系短视频&#xff1a;探索未知的视觉艺术 在短视频盛行的今天&#xff0c;各种风格和主题的作品层出不穷&#xff0c;其中&#xff0c;暗黑系短视频以其独特的魅力和深度&#xff0c;成都鼎茂宏升文化传媒公司吸引了众多观众的关注。这类视频往往带有一种神秘、压抑的氛围…

规则引擎LiteFlow发布v2.12.1版本,决策路由特性

个人博客&#xff1a;无奈何杨&#xff08;wnhyang&#xff09; 个人语雀&#xff1a;wnhyang 共享语雀&#xff1a;在线知识共享 Github&#xff1a;wnhyang - Overview 简介 标题其实是不准确的&#xff0c;了解过的会知道在LiteFlow的2.12.0已经有了决策路由的特性&…

Redis-Cluster模式基操篇

一、场景 1、搞一套6个主节点的Cluster集群 2、模拟数据正常读写 3、模拟单点故障 4、在不停服务的情况下将集群架构改为3主3从 二、环境规划 6台独立的服务器&#xff0c;端口18001~18006 192.169.14.121 192.169.14.122 192.169.14.123 192.169.14.124 192.169.14.125 192…