首页 > 其他分享 >有限状态机从设计到实践

有限状态机从设计到实践

时间:2023-03-22 22:33:06浏览次数:36  
标签:有限 void 实践 event 状态机 OrderState context OrderEvent Order


基于java实现的有限状态自动机,轻松,快捷,高效的关联状态的扭转。

背景

在日常的开发中,我们有些业务单据有非常复杂流程(它有很多状态),如果靠传统的全局属性然后通过swich和if来判断的话,扩展性差,重复代码多。通过编写一个状态管理库来解决状态变化的优点有:

  • 代码整洁,可读性强
  • 易拓展,可复用
  • 维护成本小

有限状态机

有限状态机(Finite-state machine, FSM),又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。 

有限状态机从设计到实践_FSM

  • State:状态。一个标准的状态机最少包含两个状态:初始和终态。初态是状态机初始化后所处的状态,而终态顾名思义就是状态机结束时所处的状态。其他的状态都是一些流转中停留的状态。标准的状态机还会涉及到一些中间态,存在中间态的状态机流程就会比较复杂(用处也不是特别大,而且可以通过其他方式实现),所以在目标实现的状态机里不会引入这个概念。
  • Event:事件。还有中描述叫Trigger,表达的意思都一样,就是要执行某个操作的触发器或口令:当状态机处于某个状态时,只有外界告诉状态机要干什么事情的时候,状态机才会去执行具体的行为,来完成外界想要它完成的操作。比如出去吃饭,说“点菜”,服务员才会拿着小本过来记录你要吃的菜,说的那句“点菜”,就相当于Event。
  • Action:行为。状态变更索要执行的具体行为。还是拿上面点菜的例子,服务员拿小本记录你定的菜的过程就是Action
  • Transition:流转。一个状态接收一个事件执行了某些行为到达了另外一个状态的过程就是一个Transition。定义Transition就是在定义状态机的运转流程。

项目实践

项目结构设计

│  │  └─com
│  │      └─kxtx
│  │          └─fsm
│  │              ├─builder				构建状态机,依赖core,excption,filter,config
│  │              │  ├─chain
│  │              │  │  ├─dto
│  │              │  │  └─support
│  │              │  ├─event
│  │              │  │  ├─annotation
│  │              │  │  ├─dto
│  │              │  │  └─support
│  │              │  ├─exec
│  │              │  │  ├─annotation
│  │              │  │  ├─dto
│  │              │  │  └─support
│  │              │  ├─machine
│  │              │  │  ├─annotation
│  │              │  │  ├─dto
│  │              │  │  ├─factroy
│  │              │  │  └─support
│  │              │  │      └─visit
│  │              │  ├─plugin
│  │              │  │  ├─log
│  │              │  │  │  └─support
│  │              │  │  └─support
│  │              │  ├─selector
│  │              │  └─state
│  │              │      ├─dto
│  │              │      └─support
│  │              │          └─visit
│  │              ├─config					所有配置项,依赖core,filter,exception
│  │              │  ├─annotation
│  │              │  ├─application
│  │              │  └─loader
│  │              │      └─support
│  │              ├─core					基础模块,仅依赖exception
│  │              │  ├─convert
│  │              │  │  └─support
│  │              │  ├─el
│  │              │  │  └─support
│  │              │  ├─extension
│  │              │  │  └─support
│  │              │  ├─factory
│  │              │  ├─types
│  │              │  └─utils
│  │              ├─exception				异常处理模块,不依赖任何模块
│  │              ├─filter					包含校验,后置处理,依赖core,filter,exception
│  │              │  ├─annotation
│  │              │  ├─validator
│  │              │  │  └─support
│  │              │  └─wrapper
│  │              │      └─support
│  │              └─spring					集成spring
│  │                  └─annotation

设计编码须知

1.健壮性(异常处理、灵活没打算依赖spring)           见TODO(持续进行中)
2.安全性(封装级别、客户端访问、侵入性)             见TODO(持续进行中)
3.拓展性(可插拔、多变功能柔性设计)                   见TODO(持续进行中)

代办功能事宜

Step:链式语法设计                                  √
Step:添加mvel表达式支持                            √
Step:大量反射的优化及同异步Action                  √(持续进行中)
Step:添加注解支持及枚举的兼容性                    √
Step:客户端那么多泛型好麻烦,优化客户端入口        √
Step:支持客户端更多后置处理                        √
Step:支持客户端拓展参数支持,前置处理               √
Step:添加action,transition的事件支持及多线程驱动    √
Step:插件化支持(Log记录状态机所有操作...)             √
Step:parent state支持,transition的正则匹配          √
Step:还需要支持XML?Antrl?                             ×
Step:更多执行策略支持                                 ×
Step:DependProvider替换SPI的开展                      ×
Step:关于版本化(设计考虑点)                         ×
Step:.....

验收方面

1.后续编写单元测试
2.OMS/kos/TMS安排开发进行了解及接入

交付

计划2017/5/1使用

快速开始

非spring环境(半自动化)

为啥叫半自动化呢,它的运行环境确实不是在spring环境下,你需要自己实例化

public class QuickStart_test {
    /***
     * 第一步:定义状态机扭转
     */
    @States({
            @State(name = "A", isInitial = true),
            @State(name = "A1", entryMethod = "enterA1", exitMethod = "exitA1"),
            @State(name = "A2", entryMethod = "enterA2", exitMethod = "exitA2"),
            @State(name = "A3", entryMethod = "enterA3", exitMethod = "exitA3"),
            @State(name = "A4", entryMethod = "enterA4", exitMethod = "exitA4"),
            @State(name = "A4a", parent = "A4", entryMethod = "enterA4a", exitMethod = "exitA5a", isEnd = true)
    })
    @Transitions({
            @Transition(from = "A", to = "A1", on = "ATA1", complete = "fromAToA1", whenMVEL = "PriceChecker::context.price>0&&context.price<100000"),
            @Transition(from = "A1", to = "A2", on = "A1TA2", complete = "fromA1ToA2"),
            @Transition(from = "A2", to = "A3", on = "A2TA3", complete = "fromA2ToA3"),
            @Transition(from = "A3", to = "A4", on = "A3TA4", complete = "fromA3ToA4")
    })
    interface OrderStateMachine extends StateMachine<OrderStateMachine, OrderState, OrderEvent, Order> {
        // entry states
        void enterA1(OrderState from, OrderState to, OrderEvent event, Order context);

        void enterA2(OrderState from, OrderState to, OrderEvent event, Order context);

        void enterA3(OrderState from, OrderState to, OrderEvent event, Order context);

        void enterA4(OrderState from, OrderState to, OrderEvent event, Order context);

        void enterA4a(OrderState from, OrderState to, OrderEvent event, Order context);

        // transitions
        void fromAToA1(OrderState from, OrderState to, OrderEvent event, Order context);

        void fromA1ToA2(OrderState from, OrderState to, OrderEvent event, Order context);

        void fromA2ToA3(OrderState from, OrderState to, OrderEvent event, Order context);

        void fromA3ToA4(OrderState from, OrderState to, OrderEvent event, Order context);

        // exit states
        void exitA1(OrderState from, OrderState to, OrderEvent event, Order context);

        void exitA2(OrderState from, OrderState to, OrderEvent event, Order context);

        void exitA3(OrderState from, OrderState to, OrderEvent event, Order context);

        void exitA4(OrderState from, OrderState to, OrderEvent event, Order context);

        void beforeTransitionBegin(OrderState from, OrderEvent event, Order context);

        void afterTransitionCompleted(OrderState from, OrderState to, OrderEvent event, Order context);

        void afterTransitionDeclined(OrderState from, OrderEvent event, Order context);

        void afterTransitionCausedException(OrderState fromState, OrderState toState, OrderEvent event, Order context);

    }

    /***
     * 第二步:每个扭转的内嵌实现
     */
    public static class OrderStateMachineImpl extends AbstractStateMachine<OrderStateMachine, OrderState, OrderEvent, Order> implements OrderStateMachine {
        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        @LogExec
        @Override
        public void enterA1(OrderState from, OrderState to, OrderEvent event, Order context) {
            System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
        }

        @Override
        public void enterA2(OrderState from, OrderState to, OrderEvent event, Order context) {
            System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
        }

        @Override
        public void enterA3(OrderState from, OrderState to, OrderEvent event, Order context) {
            System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
        }

        @Override
        public void enterA4(OrderState from, OrderState to, OrderEvent event, Order context) {
            System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
        }

        @Override
        public void enterA4a(OrderState from, OrderState to, OrderEvent event, Order context) {
            System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
        }

        @Override
        public void fromAToA1(OrderState from, OrderState to, OrderEvent event, Order context) {
            System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
        }

        @Override
        public void fromA1ToA2(OrderState from, OrderState to, OrderEvent event, Order context) {
            System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
        }

        @Override
        public void fromA2ToA3(OrderState from, OrderState to, OrderEvent event, Order context) {
            System.out.println(this.name);
            System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
        }

        @Override
        public void fromA3ToA4(OrderState from, OrderState to, OrderEvent event, Order context) {
            System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
        }

        @Override
        public void exitA1(OrderState from, OrderState to, OrderEvent event, Order context) {
            System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
        }

        @Override
        public void exitA2(OrderState from, OrderState to, OrderEvent event, Order context) {
            System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
        }

        @Override
        public void exitA3(OrderState from, OrderState to, OrderEvent event, Order context) {
            System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
        }

        @Override
        public void exitA4(OrderState from, OrderState to, OrderEvent event, Order context) {
            System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
        }

        @Override
        public void beforeTransitionBegin(OrderState from, OrderEvent event, Order context) {
            //order do
            System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
            super.beforeTransitionBegin(from, event, context);
        }

        @Override
        public void afterTransitionCompleted(OrderState from, OrderState to, OrderEvent event, Order context) {
            //order do
            System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
            super.afterTransitionCompleted(from, to, event, context);
        }

        @Override
        public void afterTransitionDeclined(OrderState from, OrderEvent event, Order context) {
            //order do
            System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
            super.afterTransitionDeclined(from, event, context);
        }

        @Override
        public void afterTransitionCausedException(OrderState fromState, OrderState toState, OrderEvent event, Order context) {
            //order do
            System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
            super.afterTransitionCausedException(fromState, toState, event, context);
        }
    }

    private StateMachineBuilder<OrderStateMachine, OrderState, OrderEvent, Order> builder;
    private OrderStateMachine stateMachine;
    private Stopwatch stopwatch;

    /**
     * 第三步(上):定义StateMachineBuilderFactory
     */
    @Before
    public void beforeMethod() {
        builder = StateMachineBuilderFactory.create(OrderStateMachineImpl.class, OrderState.class, OrderEvent.class, Order.class);
        builder.newPluginBuilder(new FsmListenerLogger()).install();
        stopwatch = Stopwatch.createStarted();
    }

    @Test
    public void go_handleEvent() {
        Stopwatch stopwatch = Stopwatch.createStarted();
        Order order = new Order() {{
            setId(1);
            setName("xiaomi5");
            setPrice(new BigDecimal(1));
            //setPrice(new BigDecimal(100000));
        }};
        /**
         * 第三步(下):实例化一个stateMachine
         */
        stateMachine = builder.newStateMachine(OrderState.A, new StateMachineConfig().setEnableEventListener(true));
        stateMachine.handleEvent(OrderEvent.ATA1, order);
        System.out.println("times:" + stopwatch);
        Assert.assertTrue(stateMachine.getCurrentState() == OrderState.A1);
    }

    @Test
    public void go_handleEvent_useBean() {
        Stopwatch stopwatch = Stopwatch.createStarted();
        Order order = new Order() {{
            setId(1);
            setName("xiaomi5");
            setPrice(new BigDecimal(1));
            //setPrice(new BigDecimal(100000));
        }};
        OrderStateMachineImpl beanInstance = new OrderStateMachineImpl();
        beanInstance.setName("a");
        stateMachine = builder.newStateMachine(beanInstance, OrderState.A, new StateMachineConfig().setEnableEventListener(true));
        stateMachine.handleEvent(OrderState.A2, OrderEvent.A2TA3, order);
        System.out.println(beanInstance == stateMachine);
        Assert.assertTrue(stateMachine.getCurrentState() == OrderState.A3);
    }

    @Test
    public void go_handleEvent_plugin() {
        Order order = new Order() {{
            setId(1);
            setName("xiaomi5");
            setPrice(new BigDecimal(1));
            //setPrice(new BigDecimal(100000));
        }};
        PostProcessor<OrderStateMachine> pluginPostProceesor = (m) -> {
            m.pluginsStart();
        };
        PostProcessorProvider.getInstance().register(OrderStateMachine.class, pluginPostProceesor);

        stateMachine = builder.newStateMachine(OrderState.A, new StateMachineConfig().setEnableEventListener(true));
        stateMachine.handleEvent(OrderEvent.ATA1, order);
        Assert.assertTrue(stateMachine.getCurrentState() == OrderState.A1);
        System.out.println("times:" + stopwatch);
    }

}

简单吧,确实一点都不复杂,很容易的。

spring环境(自动化)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="statemachineScannerConfigurer" class="com.kxtx.fsm.spring.StatemachineScannerConfigurer">
        <property name="basePackages" value="com.kxtx.fsm"/>
        <!--<property name="annotationClz" value="com.kxtx.fsm.spring.annotation.StatemachineService"/>-->
    </bean>
</beans>
**
 * step1
 */
@States({
        @State(name = "A", isInitial = true),
        @State(name = "A1", entryMethod = "enterA1", exitMethod = "exitA1"),
        @State(name = "A2", entryMethod = "enterA2", exitMethod = "exitA2"),
        @State(name = "A3", entryMethod = "enterA3", exitMethod = "exitA3"),
        @State(name = "A4", entryMethod = "enterA4", exitMethod = "exitA4"),
        @State(name = "A4a", parent = "A4", entryMethod = "enterA4a", exitMethod = "exitA5a", isEnd = true)
})
@Transitions({
        @Transition(from = "A", to = "A1", on = "ATA1", complete = "fromAToA1", whenMVEL = "PriceChecker::context.price>0&&context.price<100000"),
        @Transition(from = "A1", to = "A2", on = "A1TA2", complete = "fromA1ToA2"),
        @Transition(from = "A2", to = "A3", on = "A2TA3", complete = "fromA2ToA3"),
        @Transition(from = "A3", to = "A4", on = "A3TA4", complete = "fromA3ToA4")
})
@StateMachineParameters(stateType = OrderState.class, eventType = OrderEvent.class, contextType = Order.class)
public interface OrderStateMachineV2 extends StateMachineProxy {
    // entry states
    void enterA1(OrderState from, OrderState to, OrderEvent event, Order context);

    void enterA2(OrderState from, OrderState to, OrderEvent event, Order context);

    void enterA3(OrderState from, OrderState to, OrderEvent event, Order context);

    void enterA4(OrderState from, OrderState to, OrderEvent event, Order context);

    void enterA4a(OrderState from, OrderState to, OrderEvent event, Order context);

    // transitions
    void fromAToA1(OrderState from, OrderState to, OrderEvent event, Order context);

    void fromA1ToA2(OrderState from, OrderState to, OrderEvent event, Order context);

    void fromA2ToA3(OrderState from, OrderState to, OrderEvent event, Order context);

    void fromA3ToA4(OrderState from, OrderState to, OrderEvent event, Order context);

    // exit states
    void exitA1(OrderState from, OrderState to, OrderEvent event, Order context);

    void exitA2(OrderState from, OrderState to, OrderEvent event, Order context);

    void exitA3(OrderState from, OrderState to, OrderEvent event, Order context);

    void exitA4(OrderState from, OrderState to, OrderEvent event, Order context);

    void beforeTransitionBegin(OrderState from, OrderEvent event, Order context);

    void afterTransitionCompleted(OrderState from, OrderState to, OrderEvent event, Order context);

    void afterTransitionDeclined(OrderState from, OrderEvent event, Order context);

    void afterTransitionCausedException(OrderState fromState, OrderState toState, OrderEvent event, Order context);

}
/**
 * step2
 */
@StatemachineService
public class OrderStateMachineImplV2 extends AbstractStateMachineProxy implements OrderStateMachineV2 {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @LogExec
    @Override
    public void enterA1(OrderState from, OrderState to, OrderEvent event, Order context) {
        System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
    }

    @Override
    public void enterA2(OrderState from, OrderState to, OrderEvent event, Order context) {
        System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
    }

    @Override
    public void enterA3(OrderState from, OrderState to, OrderEvent event, Order context) {
        System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
    }

    @Override
    public void enterA4(OrderState from, OrderState to, OrderEvent event, Order context) {
        System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
    }

    @Override
    public void enterA4a(OrderState from, OrderState to, OrderEvent event, Order context) {
        System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
    }

    @Override
    public void fromAToA1(OrderState from, OrderState to, OrderEvent event, Order context) {
        System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
    }

    @Override
    public void fromA1ToA2(OrderState from, OrderState to, OrderEvent event, Order context) {
        System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
    }

    @Override
    public void fromA2ToA3(OrderState from, OrderState to, OrderEvent event, Order context) {
        System.out.println(this.name);
        System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
    }

    @Override
    public void fromA3ToA4(OrderState from, OrderState to, OrderEvent event, Order context) {
        System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
    }

    @Override
    public void exitA1(OrderState from, OrderState to, OrderEvent event, Order context) {
        System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
    }

    @Override
    public void exitA2(OrderState from, OrderState to, OrderEvent event, Order context) {
        System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
    }

    @Override
    public void exitA3(OrderState from, OrderState to, OrderEvent event, Order context) {
        System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
    }

    @Override
    public void exitA4(OrderState from, OrderState to, OrderEvent event, Order context) {
        System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
    }

    @Override
    public void beforeTransitionBegin(OrderState from, OrderEvent event, Order context) {
        //order do
        System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
        super.beforeTransitionBegin(from, event, context);
    }

    @Override
    public void afterTransitionCompleted(OrderState from, OrderState to, OrderEvent event, Order context) {
        //order do
        System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
        super.afterTransitionCompleted(from, to, event, context);
    }

    @Override
    public void afterTransitionDeclined(OrderState from, OrderEvent event, Order context) {
        //order do
        System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
        super.afterTransitionDeclined(from, event, context);
    }

    @Override
    public void afterTransitionCausedException(OrderState fromState, OrderState toState, OrderEvent event, Order context) {
        //order do
        System.out.println("当前执行方法:" + Thread.currentThread().getStackTrace()[1].getMethodName());
        super.afterTransitionCausedException(fromState, toState, event, context);
    }
}
/**
 * 开始使用
 */
@ContextConfiguration("classpath*:spring-statemachine.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class QuickStartV2_test {
    @Autowired
    private OrderStateMachineV2 orderStateMachine;

    @Test
    public void go_handleEvent() {
        Order order = new Order() {{
            setId(1);
            setName("xiaomi5");
            setPrice(new BigDecimal(1));
            //setPrice(new BigDecimal(100000));
        }};
        orderStateMachine.handleEvent(OrderEvent.ATA1, order);
        Assert.assertTrue(orderStateMachine.getCurrentState() == OrderState.A1);
    }
}

Q&A

如何保证线程安全?

KxtxStateMachine本身是单列模式的实现,处理是非常快的,为了不影响性能,它不保证严格意义上的线程安全,为了不影响业务的使用,使用方可以在StateMachineImpl中添加控制即可。

如何使用内嵌事务是否有影响?

KxtxStateMachine本身宿主在业务系统中(接入方),和业务请求方通一个线程,有些东西保存在ThreadLocal,因此不影响业务方事务的个性化需求

 

标签:有限,void,实践,event,状态机,OrderState,context,OrderEvent,Order
From: https://blog.51cto.com/alex/6143475

相关文章

  • 20201306——Exp2 后门原理与实践
    一、实验准备1、实验要求使用netcat获取主机操作Shell,cron启动使用socat获取主机操作Shell,任务计划启动使用MSFmeterpreter(或其他软件)生成可执行文件,利用ncat或soca......
  • 实践2
    #include<stdio.h>#include<math.h>#include<stdlib.h>#include<time.h>intmain(){charn;while(n!=EOF){ n=getchar(); getchar(); switch(n)......
  • 20201226马瑞婕《网络对抗》Exp2后门原理与实践
    目录1实验基础1.1基础知识1.1.1后门的概念常用后门工具2.实验目标3.实验环境4.实验过程4.1使用netcat获取主机操作Shell,cron启动4.1.1在主机中使用ncat-l-p1226(个人......
  • 关于微服务的自动化部署+运维,于企业发展的思考,技术性路线实践
    1、背景这段时间由于各人原因需要了解java系统部署方法。之前没有系统学习过,所以只能参考公司现有的系统部署架构。在这个学习的过程中有了个人的一些感悟+踩了一些坑。往下......
  • 「ACM 算法实践」[解题报告]组队
    分析因为时间不多了,我一开始只考虑了\(a_i\)互不相等的情况,没想到居然拿到了60昏(正确解法是贪心+优先队列。而不是从「使得人数最少的队伍人数最多」中得到的二分......
  • 「ACM 算法实践」[解题报告]时间管理大师
    分析一开始想着应该要分情况讨论,如果每台电脑的耗电量都小于\(e\),那么可以知道小Q是可以一直学习下去的,如果存在电脑的耗电量大于等于\(e\),贪心的想法是将每台电脑......
  • 「ACM 算法实践」[解题报告]沙滩拾贝
    分析因为是与运算,只有当这\(m\)个数的第\(k\)位上都是\(1\)的时候才能使得最后的数的第\(k\)位为\(1\)。为了让最后的开心程度最大,我们优先将高位取\(1\),也......
  • 数据分析第十章实践
    importpandasaspdimportmatplotlib.pyplotaspltinputfile='C:/Users/Lenore/Desktop/data\original_data.xls'#输入的数据文件data=pd.read_excel(inputfi......
  • .NET Core WebApi接口ip限流实践
    .NETCoreWebApi接口ip限流实践前言之前一直想实现接口限流,但一直没去实现,然后刚好看到一篇文章是基于AspNetCoreRateLimit组件的限流策略。这个组件不做多的介绍,想了......
  • 云原生服务网格Istio:原理、实践、架构与源码解析
    华为云原生团队600多页的Istio实战精华总结,云原生服务网格Istio:原理、实践、架构与源码解析的电子书。图书介绍《云原生服务网格Istio:原理、实践、架构与源码解析》分......