Easy Rules规则引擎(2-细节篇)

目录

  • 一、序言
  • 二、规则引擎参数配置实例
    • 1、skipOnFirstAppliedRules示例
      • (1) FizzRule
      • (2) BuzzRule
      • (3) FizzBuzzRule
      • (4) NonFizzBuzzRule
      • (5) FizzBuzzRulesLauncher
    • 2、skipOnFirstNonTriggeredRule示例
    • 3、skipOnFirstFailedRule示例
  • 三、组合规则
    • 1、UnitRuleGroup组合规则
    • 2、ActivationRuleGroup组合规则
    • 3、ConditionalRuleGroup组合规则

一、序言

在 Easy Rules规则引擎(1-基础篇) 中我们已经简单介绍了Easy Rules规则引擎的使用示例,这节我们详解介绍一下规则引擎的相关参数配置实例还有组合规则。


二、规则引擎参数配置实例

Easy Rules规则引擎支持下面参数配置:

参数名称参数类型必选默认值
rulePriorityThresholdintInteger.MAX_VALUE
skipOnFirstAppliedRulebooleanfalse
skipOnFirstFailedRulebooleanfalse
skipOnFirstNonTriggeredRulebooleanfalse
  • skipOnFirstAppliedRule: 当规则被触发并且成功执行行为后是否跳过下条规则。
  • skipOnFirstFailedRule : 当判断规则是否触发抛出异常或者触发成功但行为执行后抛出异常是否跳过下条规则。
  • skipOnFirstNonTriggeredRule : 当规则未被触发是否跳过下条规则。
  • rulePriorityThreshold : 如果规则优先级超过默认阈值,则跳过下条规则。

1、skipOnFirstAppliedRules示例

(1) FizzRule

import org.jeasy.rules.annotation.Action;
import org.jeasy.rules.annotation.Condition;
import org.jeasy.rules.annotation.Fact;
import org.jeasy.rules.annotation.Priority;
import org.jeasy.rules.annotation.Rule;/*** 被5整除的规则* @author Nick Liu* @date 2023/8/4*/
@Rule
public class FizzRule {@Conditionpublic boolean isFizz(@Fact("number") Integer number) {return number % 5 == 0;}@Actionpublic void printFizz(@Fact("number") Integer number) throws Exception {System.out.println("能被5整除的数为: " + number);}@Prioritypublic int getPriority() {return 1;}}

(2) BuzzRule

import org.jeasy.rules.annotation.Action;
import org.jeasy.rules.annotation.Condition;
import org.jeasy.rules.annotation.Fact;
import org.jeasy.rules.annotation.Priority;
import org.jeasy.rules.annotation.Rule;/*** 被7整除的规则* @author Nick Liu* @date 2023/8/4*/
@Rule
public class BuzzRule {@Conditionpublic boolean isBuzz(@Fact("number") Integer number) {return number % 7 == 0;}@Actionpublic void printBuzz(@Fact("number") Integer number) throws Exception {System.out.println("能被7整除的数为: " + number);}@Prioritypublic int getPriority() {return 2;}
}

(3) FizzBuzzRule

import org.jeasy.rules.support.composite.UnitRuleGroup;import java.util.Arrays;/*** 既能被5整除也能被7整除的规则* @author Nick Liu* @date 2023/8/4*/
public class FizzBuzzRule extends UnitRuleGroup {public FizzBuzzRule(Object... rules) {Arrays.stream(rules).forEach(super::addRule);}@Overridepublic int getPriority() {return 0;}
}

(4) NonFizzBuzzRule

import org.jeasy.rules.annotation.Action;
import org.jeasy.rules.annotation.Condition;
import org.jeasy.rules.annotation.Fact;
import org.jeasy.rules.annotation.Priority;
import org.jeasy.rules.annotation.Rule;/*** 既不能被5整除也不能被7整除的规则* @author Nick Liu* @date 2023/8/4*/
@Rule
public class NonFizzBuzzRule {@Conditionpublic boolean isNotFizzOrBuzz(@Fact("number") Integer number) {return number % 5 != 0 || number % 7 != 0;}@Actionpublic void printInput(@Fact("number") Integer number) throws Exception {System.out.println("既不能被5整除也不能被7整除的数字: " + number);}@Prioritypublic int getPriority() {return 3;}}

(5) FizzBuzzRulesLauncher

import org.jeasy.rules.api.Facts;
import org.jeasy.rules.api.Rules;
import org.jeasy.rules.api.RulesEngine;
import org.jeasy.rules.api.RulesEngineParameters;
import org.jeasy.rules.core.DefaultRulesEngine;/*** @author Nick Liu* @date 2023/8/4*/
public class FizzBuzzRulesLauncher {public static void main(String[] args) {// 如果第一条规则满足条件且行为执行成功后则跳过执行后面的规则RulesEngineParameters parameters = new RulesEngineParameters().skipOnFirstAppliedRule(true);RulesEngine rulesEngine = new DefaultRulesEngine(parameters);// 规则注册Rules rules = new Rules();rules.register(new FizzRule());rules.register(new BuzzRule());rules.register(new FizzBuzzRule(new FizzRule(), new BuzzRule()));rules.register(new NonFizzBuzzRule());// 触发规则Facts facts = new Facts();for (int count = 0; count < 100; count++) {facts.put("number", count);rulesEngine.fire(rules, facts);}}
}

上面我们设置了默认规则引擎的skipOnFirstAppliedRule属性为true,优先级最高的规则是FizzBuzzRule,这是一个组合规则,也就是说当满足该组合规则的条件,且规则行为执行成功后,就会跳过后面低优先级的所有规则。

简单来说,上面规则的执行顺序是FizzBuzzRuleFizzRuleBuzzRuleNonFizzBuzzRule,语义就是先判断数字是否能被5和7同时整除,再判断是否能被5整除,再判断是否能被7整除,最后判断是否不能被5或7整除。

程序的运行结果如下:

能被5整除的数为: 0
能被7整除的数为: 0
既不能被5整除也不能被7整除的数字: 1
既不能被5整除也不能被7整除的数字: 2
既不能被5整除也不能被7整除的数字: 3
既不能被5整除也不能被7整除的数字: 4
能被5整除的数为: 5
既不能被5整除也不能被7整除的数字: 6
能被7整除的数为: 7
既不能被5整除也不能被7整除的数字: 8
既不能被5整除也不能被7整除的数字: 9
能被5整除的数为: 10
既不能被5整除也不能被7整除的数字: 11
既不能被5整除也不能被7整除的数字: 12
既不能被5整除也不能被7整除的数字: 13
能被7整除的数为: 14
能被5整除的数为: 15
既不能被5整除也不能被7整除的数字: 16
既不能被5整除也不能被7整除的数字: 17
既不能被5整除也不能被7整除的数字: 18
既不能被5整除也不能被7整除的数字: 19
能被5整除的数为: 20
能被7整除的数为: 21
既不能被5整除也不能被7整除的数字: 22
既不能被5整除也不能被7整除的数字: 23
既不能被5整除也不能被7整除的数字: 24
能被5整除的数为: 25
既不能被5整除也不能被7整除的数字: 26
既不能被5整除也不能被7整除的数字: 27
能被7整除的数为: 28
既不能被5整除也不能被7整除的数字: 29
能被5整除的数为: 30
既不能被5整除也不能被7整除的数字: 31
既不能被5整除也不能被7整除的数字: 32
既不能被5整除也不能被7整除的数字: 33
既不能被5整除也不能被7整除的数字: 34
能被5整除的数为: 35
能被7整除的数为: 35
既不能被5整除也不能被7整除的数字: 36
既不能被5整除也不能被7整除的数字: 37
既不能被5整除也不能被7整除的数字: 38
既不能被5整除也不能被7整除的数字: 39
能被5整除的数为: 40
既不能被5整除也不能被7整除的数字: 41
能被7整除的数为: 42
既不能被5整除也不能被7整除的数字: 43
既不能被5整除也不能被7整除的数字: 44
能被5整除的数为: 45
既不能被5整除也不能被7整除的数字: 46
既不能被5整除也不能被7整除的数字: 47
既不能被5整除也不能被7整除的数字: 48
能被7整除的数为: 49
能被5整除的数为: 50
既不能被5整除也不能被7整除的数字: 51
既不能被5整除也不能被7整除的数字: 52
既不能被5整除也不能被7整除的数字: 53
既不能被5整除也不能被7整除的数字: 54
能被5整除的数为: 55
能被7整除的数为: 56
既不能被5整除也不能被7整除的数字: 57
既不能被5整除也不能被7整除的数字: 58
既不能被5整除也不能被7整除的数字: 59
能被5整除的数为: 60
既不能被5整除也不能被7整除的数字: 61
既不能被5整除也不能被7整除的数字: 62
能被7整除的数为: 63
既不能被5整除也不能被7整除的数字: 64
能被5整除的数为: 65
既不能被5整除也不能被7整除的数字: 66
既不能被5整除也不能被7整除的数字: 67
既不能被5整除也不能被7整除的数字: 68
既不能被5整除也不能被7整除的数字: 69
能被5整除的数为: 70
能被7整除的数为: 70
既不能被5整除也不能被7整除的数字: 71
既不能被5整除也不能被7整除的数字: 72
既不能被5整除也不能被7整除的数字: 73
既不能被5整除也不能被7整除的数字: 74
能被5整除的数为: 75
既不能被5整除也不能被7整除的数字: 76
能被7整除的数为: 77
既不能被5整除也不能被7整除的数字: 78
既不能被5整除也不能被7整除的数字: 79
能被5整除的数为: 80
既不能被5整除也不能被7整除的数字: 81
既不能被5整除也不能被7整除的数字: 82
既不能被5整除也不能被7整除的数字: 83
能被7整除的数为: 84
能被5整除的数为: 85
既不能被5整除也不能被7整除的数字: 86
既不能被5整除也不能被7整除的数字: 87
既不能被5整除也不能被7整除的数字: 88
既不能被5整除也不能被7整除的数字: 89
能被5整除的数为: 90
能被7整除的数为: 91
既不能被5整除也不能被7整除的数字: 92
既不能被5整除也不能被7整除的数字: 93
既不能被5整除也不能被7整除的数字: 94
能被5整除的数为: 95
既不能被5整除也不能被7整除的数字: 96
既不能被5整除也不能被7整除的数字: 97
能被7整除的数为: 98
既不能被5整除也不能被7整除的数字: 99

2、skipOnFirstNonTriggeredRule示例

public class FizzBuzzRulesLauncher {public static void main(String[] args) {RulesEngineParameters parameters = new RulesEngineParameters().skipOnFirstNonTriggeredRule(true);RulesEngine rulesEngine = new DefaultRulesEngine(parameters);// 规则注册Rules rules = new Rules();rules.register(new FizzRule());rules.register(new BuzzRule());rules.register(new FizzBuzzRule(new FizzRule(), new BuzzRule()));rules.register(new NonFizzBuzzRule());// 触发规则Facts facts = new Facts();for (int count = 0; count < 100; count++) {facts.put("number", count);rulesEngine.fire(rules, facts);}}
}

这里我们把规则引擎参数调整为skipOnFirstNonTriggeredRule,意味着当优先级最高的规则没有被触发后就跳过下面的规则,执行结果如下:

能被5整除的数为: 0
能被7整除的数为: 0
能被5整除的数为: 0
能被7整除的数为: 0
能被5整除的数为: 35
能被7整除的数为: 35
能被5整除的数为: 35
能被7整除的数为: 35
能被5整除的数为: 70
能被7整除的数为: 70
能被5整除的数为: 70
能被7整除的数为: 70

3、skipOnFirstFailedRule示例

***5整除的规则* @author Nick Liu* @date 2023/8/4*/
@Rule
public class FizzRule {@Conditionpublic boolean isFizz(@Fact("number") Integer number) {return number % 5 == 0;}@Actionpublic void printFizz(@Fact("number") Integer number) throws Exception {System.out.println("能被5整除的数为: " + number);throw new RuntimeException("该数字能被5整除");}@Prioritypublic int getPriority() {return 1;}}

这里我们修改了FizzRule规则触发后的执行行为,当数字能被5整除时,执行行为后抛出异常。

public class FizzBuzzRulesLauncher {public static void main(String[] args) {RulesEngineParameters parameters = new RulesEngineParameters().skipOnFirstFailedRule(true);RulesEngine rulesEngine = new DefaultRulesEngine(parameters);// 规则注册Rules rules = new Rules();rules.register(new FizzRule());rules.register(new BuzzRule());rules.register(new FizzBuzzRule(new FizzRule(), new BuzzRule()));rules.register(new NonFizzBuzzRule());// 触发规则Facts facts = new Facts();for (int count = 0; count < 100; count++) {facts.put("number", count);rulesEngine.fire(rules, facts);}}
}

这里我们设置了规则引擎的参数skipOnFirstFailedRule,也就是当判断规则是否触发时发生异常或者执行行为时发生异常后,就跳过下一条规则,程序运行结果如下:

能被5整除的数为: 0
既不能被5整除也不能被7整除的数字: 1
既不能被5整除也不能被7整除的数字: 2
既不能被5整除也不能被7整除的数字: 3
既不能被5整除也不能被7整除的数字: 4
能被5整除的数为: 5
既不能被5整除也不能被7整除的数字: 6
能被7整除的数为: 7
既不能被5整除也不能被7整除的数字: 7
既不能被5整除也不能被7整除的数字: 8
既不能被5整除也不能被7整除的数字: 9
能被5整除的数为: 10
既不能被5整除也不能被7整除的数字: 11
既不能被5整除也不能被7整除的数字: 12
既不能被5整除也不能被7整除的数字: 13
能被7整除的数为: 14
既不能被5整除也不能被7整除的数字: 14
能被5整除的数为: 15
既不能被5整除也不能被7整除的数字: 16
既不能被5整除也不能被7整除的数字: 17
既不能被5整除也不能被7整除的数字: 18
既不能被5整除也不能被7整除的数字: 19
能被5整除的数为: 20
能被7整除的数为: 21
既不能被5整除也不能被7整除的数字: 21
既不能被5整除也不能被7整除的数字: 22
既不能被5整除也不能被7整除的数字: 23
既不能被5整除也不能被7整除的数字: 24
能被5整除的数为: 25
既不能被5整除也不能被7整除的数字: 26
既不能被5整除也不能被7整除的数字: 27
能被7整除的数为: 28
既不能被5整除也不能被7整除的数字: 28
既不能被5整除也不能被7整除的数字: 29
能被5整除的数为: 30
既不能被5整除也不能被7整除的数字: 31
既不能被5整除也不能被7整除的数字: 32
既不能被5整除也不能被7整除的数字: 33
既不能被5整除也不能被7整除的数字: 34
能被5整除的数为: 35
既不能被5整除也不能被7整除的数字: 36
既不能被5整除也不能被7整除的数字: 37
既不能被5整除也不能被7整除的数字: 38
既不能被5整除也不能被7整除的数字: 39
能被5整除的数为: 40
既不能被5整除也不能被7整除的数字: 41
能被7整除的数为: 42
既不能被5整除也不能被7整除的数字: 42
既不能被5整除也不能被7整除的数字: 43
既不能被5整除也不能被7整除的数字: 44
能被5整除的数为: 45
既不能被5整除也不能被7整除的数字: 46
既不能被5整除也不能被7整除的数字: 47
既不能被5整除也不能被7整除的数字: 48
能被7整除的数为: 49
既不能被5整除也不能被7整除的数字: 49
能被5整除的数为: 50
既不能被5整除也不能被7整除的数字: 51
既不能被5整除也不能被7整除的数字: 52
既不能被5整除也不能被7整除的数字: 53
既不能被5整除也不能被7整除的数字: 54
能被5整除的数为: 55
能被7整除的数为: 56
既不能被5整除也不能被7整除的数字: 56
既不能被5整除也不能被7整除的数字: 57
既不能被5整除也不能被7整除的数字: 58
既不能被5整除也不能被7整除的数字: 59
能被5整除的数为: 60
既不能被5整除也不能被7整除的数字: 61
既不能被5整除也不能被7整除的数字: 62
能被7整除的数为: 63
既不能被5整除也不能被7整除的数字: 63
既不能被5整除也不能被7整除的数字: 64
能被5整除的数为: 65
既不能被5整除也不能被7整除的数字: 66
既不能被5整除也不能被7整除的数字: 67
既不能被5整除也不能被7整除的数字: 68
既不能被5整除也不能被7整除的数字: 69
能被5整除的数为: 70
既不能被5整除也不能被7整除的数字: 71
既不能被5整除也不能被7整除的数字: 72
既不能被5整除也不能被7整除的数字: 73
既不能被5整除也不能被7整除的数字: 74
能被5整除的数为: 75
既不能被5整除也不能被7整除的数字: 76
能被7整除的数为: 77
既不能被5整除也不能被7整除的数字: 77
既不能被5整除也不能被7整除的数字: 78
既不能被5整除也不能被7整除的数字: 79
能被5整除的数为: 80
既不能被5整除也不能被7整除的数字: 81
既不能被5整除也不能被7整除的数字: 82
既不能被5整除也不能被7整除的数字: 83
能被7整除的数为: 84
既不能被5整除也不能被7整除的数字: 84
能被5整除的数为: 85
既不能被5整除也不能被7整除的数字: 86
既不能被5整除也不能被7整除的数字: 87
既不能被5整除也不能被7整除的数字: 88
既不能被5整除也不能被7整除的数字: 89
能被5整除的数为: 90
能被7整除的数为: 91
既不能被5整除也不能被7整除的数字: 91
既不能被5整除也不能被7整除的数字: 92
既不能被5整除也不能被7整除的数字: 93
既不能被5整除也不能被7整除的数字: 94
能被5整除的数为: 95
既不能被5整除也不能被7整除的数字: 96
既不能被5整除也不能被7整除的数字: 97
能被7整除的数为: 98
既不能被5整除也不能被7整除的数字: 98
既不能被5整除也不能被7整除的数字: 99

可以看到,既能被5整除也能被7整除的数,如3570只打印了一次。


三、组合规则

Easy Rules允许我们创建复杂的组合规则,所谓组合规则由多个单条规则组成,实际上就是组合设计模式的一种实现。

组合规则是一种抽象概念,因为组合规则可以通过不同的方式出发。Easy Rules提供了三种组合规则的实现,这些实现可以在easy-rules-support模块中可以找到,首先介绍一下3种组合规则:

  • UnitRuleGroup: 单元规则组,里面的所有规则都会被应用。
  • ActivationRuleGroup: 激活规则组,只会触发第一条适用的规则,该规则组中的所有规则默认根据优先级排序。
  • ConditionalRuleGroup: 条件式规则则,如果最高优先级的规则可以被触发,那么才会触发其它规则组中的规则。

1、UnitRuleGroup组合规则

该组合规则判断规则是否触发的代码如下,可以看到,所有的规则如果被触发,相应的行为就会被执行。

@Override
public boolean evaluate(Facts facts) {if (!rules.isEmpty()) {for (Rule rule : rules) {if (!rule.evaluate(facts)) {return false;}}return true;}return false;
}@Override
public void execute(Facts facts) throws Exception {for (Rule rule : rules) {rule.execute(facts);}
}

2、ActivationRuleGroup组合规则

从该组合规则的源代码可以看到,该规则组中只有第一条可以被触发的规则才会执行相应的规则行为。

@Override
public boolean evaluate(Facts facts) {for (Rule rule : rules) {if (rule.evaluate(facts)) {selectedRule = rule;return true;}}return false;
}@Override
public void execute(Facts facts) throws Exception {if (selectedRule != null) {selectedRule.execute(facts);}
}

3、ConditionalRuleGroup组合规则

该组合规则的源代码如下,可以看到只有最高优先级的规则可以被触发,才会继续应用其它规则中的规则。

 @Overridepublic boolean evaluate(Facts facts) {successfulEvaluations = new HashSet<>();conditionalRule = getRuleWithHighestPriority();if (conditionalRule.evaluate(facts)) {for (Rule rule : rules) {if (rule != conditionalRule && rule.evaluate(facts)) {successfulEvaluations.add(rule);}}return true;}return false;}/*** When a conditional rule group is executed, all rules that evaluated to true* are performed in their natural order, but with the conditional rule * (the one with the highest priority) first.** @param facts The facts.** @throws Exception thrown if an exception occurs during actions performing*/@Overridepublic void execute(Facts facts) throws Exception {conditionalRule.execute(facts);for (Rule rule : sort(successfulEvaluations)) {rule.execute(facts);}}private Rule getRuleWithHighestPriority() {List<Rule> copy = sort(rules);// make sure we only have one rule with the highest priorityRule highest = copy.get(0);if (copy.size() > 1 && copy.get(1).getPriority() == highest.getPriority()) {throw new IllegalArgumentException("Only one rule can have highest priority");}return highest;}private List<Rule> sort(Set<Rule> rules) {return new ArrayList<>(new TreeSet<>(rules));}

在这里插入图片描述

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

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

相关文章

基于Java的基数排序(详述)

基于Java的基数排序&#xff08;详述&#xff09; 原理介绍Java实现文献参考 原理介绍 一、什么是基数排序 &#xff08;1&#xff09;通过键值得各个位的值&#xff0c;将要排序的元素分配至一些桶中&#xff0c;达到排序的作用 &#xff08;2&#xff09;基数排序法是属于稳…

【论文阅读笔记】Endoscopic navigation in the absence of CT imaging

论文小结 上一篇的导航导论&#xff0c;是需要先验&#xff0c;也就是需要事先拍摄堆叠的图片&#xff08;比如CT图等&#xff09;&#xff0c;在体外构建相应的3D模型&#xff0c;再与内窥镜图像进行实时匹配。对于很多情况来说&#xff0c;是无法拥有如此充足的先验的。所以&…

Unity Meta Quest MR 开发教程:(二)自定义透视 Passthrough【透视功能进阶】

文章目录 &#x1f4d5;教程说明&#x1f4d5;动态开启和关闭透视⭐方法一&#xff1a;OVRManager.instance.isInsightPassthroughEnabled⭐方法二&#xff1a;OVRPassthroughLayer 脚本中的 hidden 变量 &#x1f4d5;透视风格 Passthrough Styling⭐Inspector 面板控制⭐代码…

固定资产台账怎么管理

固定资产台账是指企业对固定资产进行登记、分类、统计和管理的账簿。固定资产管理系统是一款专业的固定资产管理软件&#xff0c;可以帮助企业实现资产全生命周期管理&#xff0c;包括资产采购、入库、领用、归还、维修、报废等环节。系统具有实时监控、预警提醒、报表分析等功…

【kubernetes系列】kubeadm证书调整

部署k8s集群之前调整 默认情况下&#xff0c;使用kubeadm部署的k8s集群的证书有效期为1年。我们可以在初始k8s集群之前就调整好时间&#xff0c;避免后期经常更新。可以使用以下脚本对kubeadm的时间调整后重新编译生成kubeadm。此脚本针对k8s1.19.16版本&#xff0c;不同版本可…

App Inventor 2 开发 ChatGPT 对话App

ChatGPT大家应该不会陌生&#xff0c;它的回答内容非常的专业及深入&#xff0c;具有实际的可指导性。我们通过App Inventor 2开发一个简单的对话App&#xff0c;先看效果&#xff1a; App Inventor 2 ChatGPT教育领域对话演示 代码块如下&#xff1a; 用到的核心组件“ChatBot…

Java注解、文件IO以及匿名函数

文章目录 1. 注解1.1 自定义注解1.2 元注解1.2.1 Target1.2.2 Retention 1.3 注解的解析 2. 文件IO2.1 非流式文件类2.2 流式文件类2.2.1 字节输入流2.2.2 字节输出流2.2.3 字符输入流2.2.4 字符输出流 3. 匿名3.1 lambda表达式3.2 方法引用 1. 注解 注解可以在类、方法、构造…

6.oracle中listagg函数使用

1. 作用 可以实现行转列&#xff0c;将多列数据聚合为一列&#xff0c;实现数据的压缩 2. 语法 listagg(measure_expr&#xff0c;delimiter) within group ( order by order_by_clause); 解释&#xff1a; measure_expr可以是基于任何列的表达式 delimiter分隔符&#xff0c…

HTML学习笔记02

HTML笔记02 页面结构分析 元素名描述header标题头部区域的内容&#xff08;用于页面或页面中的一块区域&#xff09;footer标记脚部区域的内容&#xff08;用于整个页面或页面的一块区域&#xff09;sectionWeb页面中的一块独立区域article独立的文章内容aside相关内容或应用…

红黑树(AVL树的优化)上

红黑树略胜AVL树 AVL树是一颗高度平衡搜索二叉树&#xff1a; 要求左右高度差不超过1&#xff08;严格平衡&#xff09; 有的大佬认为AVL树太过严格&#xff0c;对平衡的要求越严格&#xff0c;会带来更多的旋转&#xff08;旋转也还是会有一定的消耗&#xff01;&#xff01;…

java多线程之线程通信

java多线程文章 java多线程之线程创建和状态 java多线程之FutureTask、Future、CompletableFuture java多线程之线程池 java多线程之线程通信工具类 合理的使⽤Java多线程可以更好地利⽤服务器资源。⼀般来讲&#xff0c;线程内部有⾃⼰私 有的线程上下⽂&#xff0c;互不⼲…

WordPress使用子主题插件 Child Theme Wizard,即使主题升级也能够保留以前主题样式

修改WordPress网站样式&#xff0c;主题升级会导致自己定义设置的网站样式丢失&#xff0c;还需要重新设置&#xff0c;很繁琐工作量大&#xff0c;发现在WordPress 中有Child Theme Wizard子主题插件&#xff0c;使用Child Theme Wizard子主题插件&#xff0c;即使主题升级&am…

使用devsidecar 软件解决 git因网络问题报错的

上链接&#xff1a; https://github.com/docmirror/dev-sidecar/releases 下载你系统对应的版本 安装后根据教程设置即可 解决了git提交、拉取时报以下错误&#xff1a; Failed to connect to github.com port 443 after 21051 ms: Couldnt connect to server Recv failur…

2023年下半年西安/广州/深圳软考(中/高级)开班啦!!!

软考是全国计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试&#xff08;简称软考&#xff09;项目&#xff0c;是由国家人力资源和社会保障部、工业和信息化部共同组织的国家级考试&#xff0c;既属于国家职业资格考试&#xff0c;又是职称资格考试。 系统集成项…

智慧校园用电安全解决方案

随着科技的不断发展&#xff0c;智慧校园建设逐渐成为了教育行业的一大趋势。在这个过程中&#xff0c;电力系统作为校园基础设施的重要组成部分&#xff0c;其安全、稳定、高效的运行显得尤为重要。下面小编来为大家介绍下智慧校园用电安全解决方案吧! 一、智慧校园电力系统现…

前端知识总汇

前端知识总汇 HTML 超文本标记语言 注释 <!--单行注释--> <!-- 多行注释 --> 由于 HTML 代码杂乱无章&#xff0c;我们习惯性的用注释来划定区域方便后续的查找HTML 的文档结构 <!DOCTYPE html> <html lang"en"><!-- 定义配置给浏览…

抖店无货源和工厂直发有什么区别?聊下无货源的概念和做店思路

我是王路飞。 最近收到了几条私信&#xff0c;都是关于做抖店的&#xff0c;其中有一条吸引了我的兴趣。 他问的是&#xff1a;抖店的无货源和工厂直发有什么区别吗&#xff1f; 说实话&#xff0c;这个问题&#xff0c;我一开始是不打算回复的&#xff0c;因为没有意义。 …

C# task多线程创建,暂停,继续,结束使用

1、多线程任务创建 private void button1_Click(object sender, EventArgs e) //创建线程{CancellationToken cancellationToken tokensource.Token;Task.Run(() > //模拟耗时任务{for (int i 0; i < 100; i){if (cancellationToken.IsCancellationRequested){return;…

[C++ 网络协议] 多进程服务器端

具有代表性的并发服务器端实现模型和方法&#xff1a; 多进程服务器&#xff1a;通过创建多个进程提供服务。✔ 多路复用服务器&#xff1a;通过捆绑并统一管理I/O对象提供服务。 多线程服务器&#xff1a;通过生成与客户端等量的线程提供服务。 目录 1. 进程的概念及应用 1.…

24 - form表单验证 - bootstrap结合使用

一. flask中bootstrap的使用 16- flask-bootstrap模板的使用_一个微不足道的bug的博客-CSDN博客 二. form结合bootstrap使用 (1). form.py 进行表单验证 from flask_wtf import FlaskForm from flask_wtf.file import FileField, FileRequired, FileAllowed from wtforms impo…