充电宝项目:规则引擎Drools学习

文章目录

  • 规则引擎 Drools
    • 1 问题
    • 2 规则引擎概述
      • 2.1 规则引擎
      • 2.2 使用规则引擎的优势
      • 2.3 规则引擎应用场景
      • 2.4 Drools介绍
    • 3 Drools入门案例
      • 3.1 创建springboot项目 引入依赖
      • 3.2 添加Drools配置类
      • 3.4 创建实体类Order
      • 3.5 orderScore.drl
      • 3.6 编写测试类
    • 4 Drools基础语法
      • 4.1 规则文件构成
      • 4.2 规则体语法结构
      • 4.3 注释
      • 4.4 Pattern模式匹配
      • 4.5 比较操作符
      • 4.6 Drools内置方法
        • 4.6.1 update方法
        • 4.6.2 insert方法
        • 4.6.3 retract方法
    • 5 规则属性 attributes
      • 5.1 salience属性
      • 5.2 no-loop属性
    • 6 Drools高级语法
      • 6.1 global全局变量

规则引擎 Drools

1 问题

对于不经常变化的业务,我们通常是硬编码到程序中。但是经常变化的业务,我们就得把业务流程从代码中剥离出来,我们怎么从程序中剥离出去?这里就需要用到规则引擎了。

规则引擎可以做到把算法剥离出程序,你可以保存到TXT文件或者数据库表里面,用的时候再加载回程序。虽然加载回来的算法是字符串,但是规则引擎有办法运行这些字符串。例如商业中心人流量大的地方,共享充电宝收费就得上调一些。人流量小的地方可以下调一点。既然费用的算法经常要变动,我们肯定不能把算法写死到程序里面。我们要把算法从程序中抽离,保存到MySQL里面。将来我们要改动计费算法,直接添加一个新纪录就行了,原有记录不需要删改,程序默认使用最新的计费方式。

2 规则引擎概述

2.1 规则引擎

  • 规则引擎,全称为业务规则管理系统,英文名为BRMS(即Business Rule Management System)。规则引擎的主要思想是将应用程序中的业务决策部分分离出来,并使用预定义的语义模块编写业务决策(业务规则),由用户或开发者在需要时进行配置、管理。

  • 注意规则引擎并不是一个具体的技术框架,而是指的一类系统,即业务规则管理系统。目前市面上具体的规则引擎产品有:drools、VisualRules、iLog等。

  • 规则引擎实现了将业务决策从应用程序代码中分离出来,接收数据输入,解释业务规则,并根据业务规则做出业务决策。规则引擎其实就是一个输入输出平台

  • 系统中引入规则引擎后,业务规则不再以程序代码的形式驻留在系统中,取而代之的是处理规则的规则引擎,业务规则存储在规则库中,完全独立于程序。业务人员可以像管理数据一样对业务规则进行管理,比如查询、添加、更新、统计、提交业务规则等。业务规则被加载到规则引擎中供应用系统调用。

2.2 使用规则引擎的优势

使用规则引擎的优势如下:

  1. 业务规则与系统代码分离,实现业务规则的集中管理
  2. 在不重启服务的情况下可随时对业务规则进行扩展和维护
  3. 可以动态修改业务规则,从而快速响应需求变更
  4. 规则引擎是相对独立的,只关心业务规则,使得业务分析人员也可以参与编辑、维护系统的业务规则
  5. 减少了硬编码业务规则的成本和风险
  6. 使用规则引擎提供的规则编辑工具,使复杂的业务规则实现变得的简单

2.3 规则引擎应用场景

对于一些存在比较复杂的业务规则并且业务规则会频繁变动的系统比较适合使用规则引擎,如下:

  1. 风险控制系统----风险贷款、风险评估
  2. 反欺诈项目----银行贷款、征信验证
  3. 决策平台系统----财务计算
  4. 促销平台系统----满减、打折、加价购

2.4 Drools介绍

  • drools是一款由JBoss组织提供的基于Java语言开发的开源规则引擎,可以将复杂且多变的业务规则从硬编码中解放出来,以规则脚本的形式存放在文件或特定的存储介质中(例如存放在数据库中),使得业务规则的变更不需要修改项目代码、重启服务器就可以在线上环境立即生效。
  • drools官网地址:https://drools.org/
  • drools源码下载地址:https://github.com/kiegroup/drools

3 Drools入门案例

3.1 创建springboot项目 引入依赖

<properties><drools.version>8.41.0.Final</drools.version>
</properties>
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.drools</groupId><artifactId>drools-core</artifactId><version>${drools.version}</version></dependency><dependency><groupId>org.drools</groupId><artifactId>drools-compiler</artifactId><version>${drools.version}</version></dependency><dependency><groupId>org.drools</groupId><artifactId>drools-decisiontables</artifactId><version>${drools.version}</version></dependency><dependency><groupId>org.drools</groupId><artifactId>drools-mvel</artifactId><version>${drools.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
</dependencies>

3.2 添加Drools配置类


import org.kie.api.KieServices;
import org.kie.api.builder.*;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.internal.io.ResourceFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** 规则引擎配置类*/
@Configuration
public class DroolsConfig {private static final KieServices kieServices = KieServices.Factory.get();//制定规则文件的路径private static final String RULES_CUSTOMER_RULES_DRL = "rules/order.drl";@Beanpublic KieContainer kieContainer() {//获得Kie容器对象KieFileSystem kieFileSystem = kieServices.newKieFileSystem();kieFileSystem.write(ResourceFactory.newClassPathResource(RULES_CUSTOMER_RULES_DRL));KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);kieBuilder.buildAll();KieModule kieModule = kieBuilder.getKieModule();KieContainer kieContainer = kieServices.newKieContainer(kieModule.getReleaseId());return kieContainer;}}

说明:

  • 定义了一个 KieContainerSpring BeanKieContainer用于通过加载应用程序的/resources文件夹下的规则文件来构建规则引擎。
  • 创建KieFileSystem实例并配置规则引擎并从应用程序的资源目录加载规则的 DRL 文件。
  • 使用KieBuilder实例来构建 drools 模块。我们可以使用KieSerive单例实例来创建 KieBuilder 实例。
  • 最后,使用 KieService 创建一个 KieContainer 并将其配置为 spring bean

3.4 创建实体类Order

@Data
public class Order {private double amout;private double score;}

3.5 orderScore.drl

  • 创建规则文件resources/rules/orderScore.drl
//订单积分规则
package com.order
import com.atguigu.drools.model.Order//规则一:100元以下 不加分
rule "order_rule_1"when$order:Order(amout < 100)then$order.setScore(0);System.out.println("成功匹配到规则一:100元以下 不加分");
end//规则二:100元 - 500元 加100分
rule "order_rule_2"when$order:Order(amout >= 100 && amout < 500)then$order.setScore(100);System.out.println("成功匹配到规则二:100元 - 500元 加100分");
end//规则三:500元 - 1000元 加500分
rule "order_rule_3"when$order:Order(amout >= 500 && amout < 1000)then$order.setScore(500);System.out.println("成功匹配到规则三:500元 - 1000元 加500分");
end//规则四:1000元以上 加1000分
rule "order_rule_4"when$order:Order(amout >= 1000)then$order.setScore(1000);System.out.println("成功匹配到规则四:1000元以上 加1000分");
end

3.6 编写测试类

import org.junit.jupiter.api.Test;
import com.atguigu.drools.model.Order;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
class DroolsDemosApplicationTests {@Autowiredprivate KieContainer kieContainer;@Testpublic void test(){//从Kie容器对象中获取会话对象KieSession session = kieContainer.newKieSession();//Fact对象,事实对象Order order = new Order();order.setAmout(1300);//将Order对象插入到工作内存中session.insert(order);//激活规则,由Drools框架自动进行规则匹配,如果规则匹配成功,则执行当前规则session.fireAllRules();//关闭会话session.dispose();System.out.println("订单金额:" + order.getAmout() +",添加积分:" + order.getScore());}}
  • 使用drools规则引擎主要工作就是编写规则文件,在规则文件中定义跟业务相关的业务规则。规则定义好后就需要调用drools提供的API将数据提供给规则引擎进行规则模式匹配,规则引擎会执行匹配成功的规则并将计算的结果返回给我们。

  • 使用规则引擎时业务规则可以做到动态管理。业务人员可以像管理数据一样对业务规则进行管理,比如查询、添加、更新、统计、提交业务规则等。这样就可以做到在不重启服务的情况下调整业务规则。

4 Drools基础语法

4.1 规则文件构成

  • 在使用Drools时非常重要的一个工作就是编写规则文件,通常规则文件的后缀为.drl。

drl是Drools Rule Language的缩写。在规则文件中编写具体的规则内容。

一套完整的规则文件内容构成如下:

关键字描述
package包名,只限于逻辑上的管理,同一个包名下的查询或者函数可以直接调用
import用于导入类或者静态方法
global全局变量
function自定义函数
query查询
rule end规则体

Drools支持的规则文件,除了drl形式,还有Excel文件类型的。

4.2 规则体语法结构

规则体是规则文件内容中的重要组成部分,是进行业务规则判断、处理业务结果的部分。

规则体语法结构如下:

rule "ruleName"attributeswhenLHS thenRHS
end

rule:关键字,表示规则开始,参数为规则的唯一名称。
attributes:规则属性,是rule与when之间的参数,为可选项。
when:关键字,后面跟规则的条件部分。
LHS(Left Hand Side):是规则的条件部分的通用名称。它由零个或多个条件元素组成。如果LHS为空,则它将被视为始终为true的条件元素。 (左手边)
then:关键字,后面跟规则的结果部分。
RHS(Right Hand Side):是规则的后果或行动部分的通用名称。 (右手边)
end:关键字,表示一个规则结束。

4.3 注释

  • 在drl形式的规则文件中使用注释和Java类中使用注释一致,分为单行注释和多行注释。

单行注释用"//“进行标记,多行注释以”/“开始,以”/"结束。

//规则rule1的注释,这是一个单行注释
rule "rule1"whenthenSystem.out.println("rule1触发");
end/*
规则rule2的注释,
这是一个多行注释
*/
rule "rule2"whenthenSystem.out.println("rule2触发");
end

4.4 Pattern模式匹配

前面我们已经知道了Drools中的匹配器可以将Rule Base中的所有规则与Working Memory中的Fact对象进行模式匹配,那么我们就需要在规则体的LHS部分定义规则并进行模式匹配。LHS部分由一个或者多个条件组成,条件又称为pattern。
pattern的语法结构为:绑定变量名:Object(Field约束)
其中绑定变量名可以省略,通常绑定变量名的命名一般建议以$开始。如果定义了绑定变量名,就可以在规则体的RHS部分使用此绑定变量名来操作相应的Fact对象。Field约束部分是需要返回true或者false的0个或多个表达式。例如入门案例中:

//规则二:100元 - 500元 加100分
rule "order_rule_2"when$order:Order(amout >= 100 && amout < 500)then$order.setScore(100);System.out.println("成功匹配到规则二:100元 - 500元 加100分");
end

通过上面的例子我们可以知道,匹配的条件为:
1、工作内存中必须存在Order这种类型的Fact对象-----类型约束
2、Fact对象的amout属性值必须大于等于100------属性约束
3、Fact对象的amout属性值必须小于100------属性约束
以上条件必须同时满足当前规则才有可能被激活。

4.5 比较操作符

Drools提供的比较操作符,如下表:

符号说明
>大于
<小于
>=大于等于
<=小于等于
==等于
!=不等于
contains检查一个Fact对象的某个属性值是否包含一个指定的对象值
not contains检查一个Fact对象的某个属性值是否不包含一个指定的对象值
memberOf判断一个Fact对象的某个属性是否在一个或多个集合中
not memberOf判断一个Fact对象的某个属性是否不在一个或多个集合中
matches判断一个Fact对象的属性是否与提供的标准的Java正则表达式进行匹配
not matches判断一个Fact对象的属性是否不与提供的标准的Java正则表达式进行匹配

前6个比较操作符和Java中的完全相同。

4.6 Drools内置方法

规则文件的RHS部分的主要作用是通过插入,删除或修改工作内存中的Fact数据,来达到控制规则引擎执行的目的。Drools提供了一些方法可以用来操作工作内存中的数据,**操作完成后规则引擎会重新进行相关规则的匹配,**原来没有匹配成功的规则在我们修改数据完成后有可能就会匹配成功了。

4.6.1 update方法

update方法的作用是更新工作内存中的数据,并让相关的规则重新匹配。 (要避免死循环)

参数:

//Fact对象,事实对象
Order order = new Order();
order.setAmout(30);

规则:

//规则一:100元以下 不加分
rule "order_rule_1"when$order:Order(amout < 100)then$order.setAmout(150);update($order) //update方法用于更新Fact对象,会导致相关规则重新匹配System.out.println("成功匹配到规则一:100元以下 不加分");
end//规则二:100元 - 500元 加100分
rule "order_rule_2"when$order:Order(amout >= 100 && amout < 500)then$order.setScore(100);System.out.println("成功匹配到规则二:100元 - 500元 加100分");
end

在更新数据时需要注意防止发生死循环。

4.6.2 insert方法
  • insert方法的作用是向工作内存中插入数据,并让相关的规则重新匹配。
//规则一:100元以下 不加分
rule "order_rule_1"when$order:Order(amout < 100)thenOrder order = new Order();order.setAmout(130);insert(order);      //insert方法的作用是向工作内存中插入Fact对象,会导致相关规则重新匹配System.out.println("成功匹配到规则一:100元以下 不加分");
end//规则二:100元 - 500元 加100分
rule "order_rule_2"when$order:Order(amout >= 100 && amout < 500)then$order.setScore(100);System.out.println("成功匹配到规则二:100元 - 500元 加100分");
end
4.6.3 retract方法

retract方法的作用是删除工作内存中的数据,并让相关的规则重新匹配。

//规则一:100元以下 不加分
rule "order_rule_1"when$order:Order(amout < 100)thenretract($order)      //retract方法的作用是删除工作内存中的Fact对象,会导致相关规则重新匹配System.out.println("成功匹配到规则一:100元以下 不加分");
end

5 规则属性 attributes

Drools中提供的属性如下表(部分属性):

属性名说明
salience指定规则执行优先级
dialect指定规则使用的语言类型,取值为java和mvel
enabled指定规则是否启用
date-effective指定规则生效时间
date-expires指定规则失效时间
activation-group激活分组,具有相同分组名称的规则只能有一个规则触发
agenda-group议程分组,只有获取焦点的组中的规则才有可能触发
timer定时器,指定规则触发的时间
auto-focus自动获取焦点,一般结合agenda-group一起使用
no-loop防止死循环

重点说一下我们项目需要使用的属性

5.1 salience属性

  • salience属性用于指定规则的执行优先级,取值类型为Integer数值越大越优先执行。每个规则都有一个默认的执行顺序,如果不设置salience属性,规则体的执行顺序为由上到下。可以通过创建规则文件salience.drl来测试salience属性,内容如下:
package com.orderrule "rule_1"wheneval(true)thenSystem.out.println("规则rule_1触发");
endrule "rule_2"wheneval(true)thenSystem.out.println("规则rule_2触发");
endrule "rule_3"wheneval(true)thenSystem.out.println("规则rule_3触发");
end
  • 由于以上三个规则没有设置salience属性,所以执行的顺序是按照规则文件中规则的顺序由上到下执行的。接下来修改一下文件内容:
package com.orderrule "rule_1"salience 9wheneval(true)thenSystem.out.println("规则rule_1触发");
endrule "rule_2"salience 10wheneval(true)thenSystem.out.println("规则rule_2触发");
endrule "rule_3"salience 8wheneval(true)thenSystem.out.println("规则rule_3触发");
end
  • 规则文件执行的顺序是按照我们设置的salience值由大到小顺序执行的。
  • 建议在编写规则时使用salience属性明确指定执行优先级。

5.2 no-loop属性

  • no-loop属性用于防止死循环,当规则通过update之类的函数修改了Fact对象时,可能使当前规则再次被激活从而导致死循环。取值类型为Boolean,默认值为false,测试步骤如下:
//订单积分规则
package com.order
import com.atguigu.drools.model.Order//规则一:100元以下 不加分
rule "order_rule_1"no-loop true         //防止陷入死循环when$order:Order(amout < 100)then$order.setScore(0);update($order)System.out.println("成功匹配到规则一:100元以下 不加分");
end
  • 通过控制台可以看到,由于没有设置no-loop属性的值,所以发生了死循环。接下来设置no-loop的值为true再次测试则不会发生死循环。

6 Drools高级语法

关键字描述
package包名,只限于逻辑上的管理,同一个包名下的查询或者函数可以直接调用
import用于导入类或者静态方法
global全局变量
function自定义函数
query查询
rule end规则体

6.1 global全局变量

  • global关键字用于在规则文件中定义全局变量,它可以让应用程序的对象在规则文件中能够被访问。可以用来为规则文件提供数据或服务。
  • 语法结构为:global 对象类型 对象名称

在使用global定义的全局变量时有两点需要注意:

  1. 如果对象类型为包装类型时,在一个规则中改变了global的值,那么只针对当前规则有效,对其他规则中的global不会有影响。可以理解为它是当前规则代码中的global副本,规则内部修改不会影响全局的使用。
  2. 如果对象类型为集合类型或JavaBean时,在一个规则中改变了global的值,对java代码和所有规则都有效。

  • 订单Order:
package com.atguigu.drools.model;public class Order {private double amout;public double getAmout() {return amout;}public void setAmout(double amout) {this.amout = amout;}}
  • 积分Integral:
package com.atguigu.drools.model;public class Integral {private double score;public double getScore() {return score;}public void setScore(double score) {this.score = score;}
}
  • 规则文件:
//订单积分规则
package com.order
import com.atguigu.drools.model.Orderglobal com.atguigu.drools.model.Integral integral;//规则一:100元以下 不加分
rule "order_rule_1"no-loop true         //防止陷入死循环when$order:Order(amout < 100)thenintegral.setScore(10);update($order)System.out.println("成功匹配到规则一:100元以下 不加分");
end
  • 测试:
@Test
public void test1(){//从Kie容器对象中获取会话对象KieSession session = kieContainer.newKieSession();//Fact对象,事实对象Order order = new Order();order.setAmout(30);//全局变量Integral integral = new Integral();session.setGlobal("integral", integral);//将Order对象插入到工作内存中session.insert(order);//激活规则,由Drools框架自动进行规则匹配,如果规则匹配成功,则执行当前规则session.fireAllRules();//关闭会话session.dispose();System.out.println("订单金额:" + order.getAmout());System.out.println("添加积分:" + integral.getScore());
}

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

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

相关文章

HTML、CSS 和 JavaScript 常见用法及使用规范

一、HTML 深度剖析 1. 文档类型声明 HTML 文档开头的 <!DOCTYPE html> 声明告知浏览器当前文档使用的是 HTML5 标准。它是文档的重要元信息&#xff0c;能确保浏览器以标准模式渲染页面&#xff0c;避免怪异模式下的兼容性问题。 2. 元数据标签 <meta> 标签&am…

基于CNN+ViT的蔬果图像分类实验

本文只是做一个简单融合的实验&#xff0c;没有任何新颖&#xff0c;大家看看就行了。 1.数据集 本文所采用的数据集为Fruit-360 果蔬图像数据集&#xff0c;该数据集由 Horea Mureșan 等人整理并发布于 GitHub&#xff08;项目地址&#xff1a;Horea94/Fruit-Images-Datase…

Ubuntu24.04安装libgl1-mesa-glx 报错,软件包缺失

在 Ubuntu 24.04 系统中&#xff0c;您遇到的 libgl1-mesa-glx 软件包缺失问题可能是由于该包在最新的 Ubuntu 版本中被重命名为 libglx-mesa0。以下是针对该问题的详细解决方案&#xff1a; 1. 问题原因分析 包名称变更&#xff1a;在 Ubuntu 24.04 中&#xff0c;libgl1-me…

webpack vite

​ 1、webpack webpack打包工具&#xff08;重点在于配置和使用&#xff0c;原理并不高优。只在开发环境应用&#xff0c;不在线上环境运行&#xff09;&#xff0c;压缩整合代码&#xff0c;让网页加载更快。 前端代码为什么要进行构建和打包&#xff1f; 体积更好&#x…

如何在爬虫中合理使用海外代理?在爬虫中合理使用海外ip

我们都知道&#xff0c;爬虫工作就是在各类网页中游走&#xff0c;快速而高效地采集数据。然而如果目标网站分布在多个国家或者存在区域性限制&#xff0c;那靠普通的网络访问可能会带来诸多阻碍。而这时&#xff0c;“海外代理”俨然成了爬虫工程师们的得力帮手&#xff01; …

数据仓库分层存储设计:平衡存储成本与查询效率

数据仓库分层存储不仅是一个技术问题,更是一种艺术:如何在有限的资源下,让数据既能快速响应查询,又能以最低的成本存储? 目录 一、什么是数据仓库分层存储? 二、分层存储的体系架构 1. 数据源层(ODS,Operational Data Store) 2. 数据仓库层(DW,Data Warehouse)…

YOLO学习笔记 | 基于YOLOv8的植物病害检测系统

以下是基于YOLOv8的植物病害检测系统完整技术文档,包含原理分析、数学公式推导及代码实现框架。 基于YOLOv8的智能植物病害检测系统研究 摘要 针对传统植物病害检测方法存在的效率低、泛化性差等问题,本研究提出一种基于改进YOLOv8算法的智能检测系统。通过设计轻量化特征提…

高级语言调用C接口(二)回调函数(4)Python

前面2篇分别说了java和c#调用C接口&#xff0c;参数为回调函数&#xff0c;回调函数中参数是结构体指针。 接下来说下python的调用方法。 from ctypes import * import sysclass stPayResult(Structure):_pack_ 4 # 根据实际C结构体的对齐方式设置&#xff08;常见值为1,4,…

springboot启动动态定时任务

1.自定义定时任务线程池 package com.x.devicetcpserver.global.tcp.tcpscheduler;import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotatio…

pytorch框架认识--手写数字识别

手写数字是机器学习中非常经典的案例&#xff0c;本文将通过pytorch框架&#xff0c;利用神经网络来实现手写数字识别 pytorch中提供了手写数字的数据集&#xff0c;我们可以直接从pytorch中下载 MNIST中包含70000张手写数字图像&#xff1a;60000张用于训练&#xff0c;10000…

WPF 使用依赖注入后关闭窗口程序不结束

原因是在ViewModel中在构造函数中注入了Window 对象&#xff0c;即使没有使用&#xff0c;主窗口关闭程序不会退出&#xff0c;即使 ViewModel 是 AddTransient 注入的。 解决方法&#xff1a;不使用构造函数注入Window&#xff0c;通过GetService获取Window 通过注入对象调用…

用户管理(添加和删除,查询信息,切换用户,查看登录用户,用户组,配置文件)

目录 添加和删除用户 查询用户信息 切换用户 查看当前的操作用户是谁 查看首次登录的用户是谁 用户组&#xff08;对属于同个角色的用户统一管理&#xff09; 新增组 删除组 添加用户的同时&#xff0c;指定组 修改用户的组 组的配置文件&#xff08;/etc/group&…

PyTorch学习-小土堆教程

网络搭建torch.nn.Module 卷积操作 torch.nn.functional.conv2d(input, weight, biasNone, stride1, padding0, dilation1, groups1) 神经网络-卷积层

MVCC详细介绍及面试题

目录 1.什么是mvcc&#xff1f; 2.问题引入 3. MVCC实现原理&#xff1f; 3.1 隐藏字段 3.2 undo log 日志 3.2.1 undo log版本链 3.3 readview 3.3.1 当前读 ​编辑 3.3.2 快照读 3.3.3 ReadView中4个核心字段 3.3.4 版本数据链访问的规则&#xff08;了解&#x…

企业级Active Directory架构设计与运维管理白皮书

企业级Active Directory架构设计与运维管理白皮书 第一章 多域架构设计与信任管理 1.1 企业域架构拓扑设计 1.1.1 林架构设计规范 林根域规划原则&#xff1a; 采用三段式域名结构&#xff08;如corp.enterprise.com&#xff09;&#xff0c;避免使用不相关的顶级域名架构主…

android11 DevicePolicyManager浅析

目录 &#x1f4d8; 简单定义 &#x1f4d8;应用启用设备管理者 &#x1f4c2; 文件位置 &#x1f9e0; DevicePolicyManager 功能分类举例 &#x1f6e1;️ 1. 安全策略控制 &#x1f4f7; 2. 控制硬件功能 &#x1f9f0; 3. 应用管理 &#x1f512; 4. 用户管理 &am…

Java学习手册:Java线程安全与同步机制

在Java并发编程中&#xff0c;线程安全和同步机制是确保程序正确性和数据一致性的关键。当多个线程同时访问共享资源时&#xff0c;如果不加以控制&#xff0c;可能会导致数据不一致、竞态条件等问题。本文将深入探讨Java中的线程安全问题以及解决这些问题的同步机制。 线程安…

PyTorch核心函数详解:gather与where的实战指南

PyTorch中的torch.gather和torch.where是处理张量数据的关键工具&#xff0c;前者实现基于索引的灵活数据提取&#xff0c;后者完成条件筛选与动态生成。本文通过典型应用场景和代码演示&#xff0c;深入解析两者的工作原理及使用技巧&#xff0c;帮助开发者提升数据处理的灵活…

声学测温度原理解释

已知声速&#xff0c;就可以得到温度。 不同温度下的胜诉不同。 25度的声速大约346m/s 绝对温度-273度 不同温度下的声速。 FPGA 通过测距雷达测温度&#xff0c;固定测量距离&#xff0c;或者可以测出当前距离。已知距离&#xff0c;然后雷达发出声波到接收到回波的时间&a…

【网络篇】UDP协议的封装分用全过程

大家好呀 我是浪前 今天讲解的是网络篇的第二章&#xff1a;UDP协议的封装分用 我们的协议最开始是OSI七层网络协议 这个OSI 七层网络协议 是计算机的大佬写的&#xff0c;但是这个协议一共有七层&#xff0c;太多了太麻烦了&#xff0c;于是我们就把这个七层网络协议就简化为…