![af2e656651d7b7596a5b7d05d5faaebf.png](https://i-blog.csdnimg.cn/blog_migrate/80f21047e6b465fcdf13adb627e5abcc.jpeg)
好久不见,最近事情好多,越不写越不敢写,感觉等了这么久,要不要写得更好一些才能对得起自已。所以看的都是更深的问题,今天我尝试聊一下yarn的状态机设计,这块我不是第一天看了,之前也看了几天,虽然不是一直看,但是只要有时间都要看一点。这块还是很体现设计的。但是不好理解,更不好用语言来表达,所以我试着聊聊,不一定能说清楚。
下面我们就开始聊,首先咱们先说一下状态机是干啥的,这么个上古概念为什么hadoop这么流行的系统还在使用?先来回答第一个问题其实这个东西是很实用,也很基础的。在系统级开发中的作用很大,之前写c++的时候经常用到,只是java这块大家习惯了spring的产品化。
不多说了,我们看看状态机的实现吧,首先我们看一下StateMachine接口,这是个范性接口,里面定义了三个概念,如下所示:
STATE,状态
EVENTTYPE,事件类型
EVENT,事件
状态机就是状态的变化管理,所以STATE代理的就是这个状态,而EVENTTYPE代表的事件类型,也就是触发一个事件的条件,事件则是真正的处理逻辑。了解了这三个重要概念我们再看一下这个接口的重要方法:
STATE getCurrentState();
STATE doTransition(EVENTTYPE eventType, EVENT event);
getCurrentState这个大家一看就清楚是获取当前的状态,而doTransition则是最核心的状态变化,需要关注二点,第一是参数,这里的两个参数的做用就是接收到特定的事件类型,然后触发对应的事件。第二是返回值STATE,大家注意到了吧也就是执行完这个方法后会从之前的状态转变到另一个状态,以此来实现状态的转变。
![5a22cd6fef808ef067009b5252073156.png](https://i-blog.csdnimg.cn/blog_migrate/8ae408ef6c930a48e55ce8d3715cd995.jpeg)
了解了StateMachine接口,就知道了状态机要做什么。那么我们再看一个具体的实现类来了解hadoop中是如何实现StateMachine接口的。InternalStateMachine是在hadoop中的一个具体实现类,我们首先看一下他的成员都有哪些:
OPERAND operand;
STATE currentState;
StateTransitionListener listener;
Operand是操作对象,也就是状态机将控制的具体对象。currentState就是当前状态,listener这个是监听器,也就是在特定是时机通知相关对象的机制,这里可以先忽略。
接下来看一下核心方法doTransition方法,这里面最关键的就是下面这句。
currentState = StateMachineFactory.this.doTransition(
operand,
currentState,
eventType,
event);
首先他调用了StateMachineFactory中的doTransition方法去实际处理这个状态转化。这个方法返回的结果就是新的状态。
这里要解释一下StateMachineFactory.this的用法,这个在工场类中很常见。实现的目的就是可以在内部类中访问创建内部类的真实父类的方法,为什么这么绕着说呢,是因为类有可能多重派生。比如a继承b,b继承c。然后d是c中的内部类,当我用a去创建d的时候。this指代的是a而不是b。哎,能听懂的听懂,不能懂的也不影响,我们接着说状态机。
那么我们就要看一下StateMachineFactory类了。先来看一下他的主要成员:
TransitionsListNode transitionsListNode;
Map>> stateMachineTable;
其实这两个是一回事,transitionsListNode是一个单链表是用于生成stateMachineTable的。而stateMachineTable是一个二层的Map。第一层是状态与Map的映射。第二层是事件类型与Transition的的映射。通俗一点的解释,就是一个状态对就多个事件类型,不同的事件类型对应Transition类。这样我们就清楚了状态转换的内核原理。下面我们再来看一下Transition接口。很直接只有一个方法:doTransition。拿SingleInternalArc实现类来举例,我们看SingleInternalArc的成员有:
STATE postState;
SingleArcTransition hook;
postState就是这个转化的目的状态。而SingleArcTransition这个接口就是在这个转化中真实处理的逻辑。所有状态转化实现类都要实现这个接口。
![eef998b67b082c9007ad6ad260d0fa74.png](https://i-blog.csdnimg.cn/blog_migrate/acfd22996ebad0aec7a88ec16707b4be.jpeg)
到这,状态机的原理和关键代码已经讲完了。希望对喜欢代码的朋友有点帮助。其实在我们的实际工作中很多时候都可以用这个设计模式来解决问题。比如汽车有启动和停止两种状态。在停止状态下踩油门是没有用的,而在启动状态下足彩油门则可以加速。当然这样的例子很多。大家可以多思考,通过使用状态机可以使我们的代码更生动更易于理解。而且配合uml的状态图则会使这种设计更加直观。