状态机一般和事件驱动结合在一起用的,我们继续上一篇的例子。
1.定时task的任务状态
package com.eg2;
public enum TaskStateInternal {
RUN,
END
}
2.定义状态机
package com.eg2;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.hadoop.yarn.event.EventHandler;
import org.apache.hadoop.yarn.state.SingleArcTransition;
import org.apache.hadoop.yarn.state.StateMachine;
import org.apache.hadoop.yarn.state.StateMachineFactory;
import com.eg1.TaskEvent;
import com.eg1.TaskEventType;
public class TaskStateMachine implements EventHandler<TaskEvent> {
private final String taskID;
private EventHandler eventHandler;
private final Lock writeLock;
private final Lock readLock;
protected static final
StateMachineFactory<TaskStateMachine,TaskStateInternal,TaskEventType,TaskEvent>
stateMachineFactory
=new StateMachineFactory<TaskStateMachine,TaskStateInternal,TaskEventType,TaskEvent>
(TaskStateInternal.RUN)
.addTransition(TaskStateInternal.RUN, TaskStateInternal.END, TaskEventType.T_KILL,new KillTransition())
.addTransition(TaskStateInternal.RUN, TaskStateInternal.END, TaskEventType.T_SCHEDULE,new ScheduleTransition())
.installTopology();
private final StateMachine<TaskStateInternal, TaskEventType, TaskEvent> stateMachine;
public StateMachine<TaskStateInternal, TaskEventType, TaskEvent> getStateMachine() {
return stateMachine;
}
public TaskStateMachine(String taskID,EventHandler eventHandler){//单独观察状态机,EventHandler都应该可以不用传吧
this.taskID=taskID;
ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
this.readLock=readWriteLock.readLock();
this.writeLock=readWriteLock.writeLock();
this.eventHandler =eventHandler;
stateMachine=stateMachineFactory.make(this);
}
public static class KillTransition implements SingleArcTransition<TaskStateMachine, TaskEvent>{
@Override
public void transition(TaskStateMachine arg0, TaskEvent arg1) {
System.out.println("KillTransition");
arg0.eventHandler.handle(new TaskEvent("task1",TaskEventType.T_KILL));
}
}
public static class ScheduleTransition implements SingleArcTransition<TaskStateMachine, TaskEvent>{
@Override
public void transition(TaskStateMachine arg0, TaskEvent arg1) {
System.out.println("ScheduleTransition");
arg0.eventHandler.handle(new TaskEvent("task1",TaskEventType.T_SCHEDULE));
}
}
@Override
public void handle(TaskEvent arg0) {
try{
writeLock.lock();
TaskStateInternal oldstate = getInternalState();
System.out.println("machine handler start ,state:"+oldstate);
getStateMachine().doTransition(arg0.getType(), arg0);
System.out.println("machine handler end , state:"+getInternalState());
}finally{
writeLock.unlock();
}
}
public TaskStateInternal getInternalState(){
try{
readLock.lock();
return getStateMachine().getCurrentState();
}finally{
readLock.unlock();
}
}
}
3.测试类,我们将一个类copy一份简单修改,因为构造的时候需要传EventHandler,我们直接用上一例的TaskEventDisptacher
【private class TaskEventDisptacher implements EventHandler<TaskEvent>】
package com.eg2;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.service.CompositeService;
import org.apache.hadoop.service.Service;
import org.apache.hadoop.yarn.event.AsyncDispatcher;
import org.apache.hadoop.yarn.event.Dispatcher;
import org.apache.hadoop.yarn.event.EventHandler;
import com.eg1.TaskEvent;
import com.eg1.TaskEventType;
public class SimpleMRAppMaster extends CompositeService {
private Dispatcher dispatcher;
public Dispatcher getDispatcher() {
return dispatcher;
}
public SimpleMRAppMaster(String name) {
super(name);
}
@Override
protected void serviceInit(Configuration arg0) throws Exception {
dispatcher = new AsyncDispatcher();
dispatcher.register(TaskEventType.class, new TaskEventDisptacher());
addService((Service)dispatcher);
super.serviceInit(arg0);
}
private class TaskEventDisptacher implements EventHandler<TaskEvent>{
@Override
public void handle(TaskEvent arg0) {
// TaskStateMachine machine = new TaskStateMachine("TaskStateMachine",this);
// machine.handle(arg0);
// 以上代码是可以调用状态机去发送事件,但是状态机器handle的时候又发送了本事件,造成死循环。所以这里暂时不这样使用
if(arg0.getType() == TaskEventType.T_KILL){
System.out.println("run kill");
}else if(arg0.getType() == TaskEventType.T_SCHEDULE){
System.out.println("run schedule");
}
}
}
//测试入口
public static void main(String[] args) throws Exception {
//因为没有TaskEventDisptacher中handle()调用状态机,所以也不需要启动service之类的,我们直接在下面new状态机测试
TaskStateMachine machine = new TaskStateMachine("TaskStateMachine",new SimpleMRAppMaster("SimpleMRAppMaster").new TaskEventDisptacher());
machine.handle(new TaskEvent("task1",TaskEventType.T_KILL));
// machine.handle(new TaskEvent("task1",TaskEventType.T_SCHEDULE));//如果连续执行,抛出异常,因为kill后状态为END无法执行schedule事件
}
}