JADE学习笔记【2】
Agent Behaviour
简单行为(Simple Behaviour)
一次性行为(OneShotBehaviour)
OneShotBehaviour是Simple Behaviour的子类,它的特点是action()方法只执行一次,因为它的done()方法永远返回true,而且被声明为final,不能重写。
package MyFirstAgent;
import jade.core.Agent;
import jade.core.behaviours.OneShotBehaviour;
public class MyShotAgent extends Agent {
@Override
protected void setup() {
this.addBehaviour(new mybehaviour());
}
}
class mybehaviour extends OneShotBehaviour{
@Override
public void action() {
System.out.println("I am a oneshot agent");
}
}
输出:
。。。。。。略
I am a oneshot agent
还有一个WakerBehaviour,类似闹钟,提供唤醒服务,超出指定时间后只执行一次的Behaviour,在给定一段时间后,WakerBehaviour执行其handleElapsedTimeout()
该方法已经被废弃,使用onWake()
抽象方法,方法结束后,行为也将结束。
package MyFirstAgent;
import jade.core.Agent;
import jade.core.behaviours.WakerBehaviour;
public class WakerAgent extends Agent {
@Override
protected void setup() {
System.out.println("Adding waker behaviour");
addBehaviour(new WakerBehaviour(this,5000) {
@Override//使用onWake()方法
protected void handleElapsedTimeout() {
System.out.println("5秒后");
}
});
}
}
循环行为(CyclicBehaviour)
也是SimpleBehaviour的子类,不需要对done()方法重写,返回值恒为false。
package MyFirstAgent;
import jade.core.Agent;
import jade.core.behaviours.CyclicBehaviour;
import jade.lang.acl.ACLMessage;
public class ReceiverAgent extends Agent {
@Override
protected void setup() {
this.addBehaviour(new CyclicBehaviour() {
@Override
public void action() {
ACLMessage msg=receive();
if (msg!=null){
System.out.println("I received this message:"+msg.getContent()+",this message is from" +
msg.getSender());
}
}
});
}
}
一个特殊的循环行为(TickerBehaviour)
有时,Agent需要周期性的执行某项动作,使用TickerBehaviour实现。派生自SimpleBehaviour类。
定义形式为:
public abstract class TickerBehaviour extends SimpleBehaviour{..}
构造方法:
public TickerBehaviour(Agent a,ling period){
super(a);
if(period<=0){
throw new IllegalArgumentException("Period must be greater than 0");
}
this.period=period;
}
在构造方法中,时间间隔period单位为ms。action和done方法都带有final关键字,需要实现onTick()
犯法,在该方法中定义周期性执行的动作。行为不会执行完成,除非它被移除或者调用stop()方法。
随时可以通过Agent类的removeBehaviour()
方法去除Agent携带的行为,调用这个方法可以去除Agent当前行为执行队列中的行为。每个行为都拥有一个叫做myAgent的成员变量,表示执行它的Agent,这提供了一种在行为内部访问Agent资源的简单方法。一旦行为对象被执行过一次后,如果需要再次执行时,必须先调用它的reset()
方法,否则可能导致意外。
组合行为(Composite Behaviour)
顺序行为(SequentialBehaviour)
一个接一个地执行其子行为,直到最后一个子行为执行完毕,按顺序执行,只有当前任务执行完毕,下一个子任务才会被执行。
package MyFirstAgent;
import jade.core.Agent;
import jade.core.behaviours.OneShotBehaviour;
import jade.core.behaviours.SequentialBehaviour;
import jade.core.behaviours.SimpleBehaviour;
import jade.core.behaviours.WakerBehaviour;
public class MysequentialAgent extends Agent {
@Override
protected void setup() {
SequentialBehaviour sb=new SequentialBehaviour();
sb.addSubBehaviour(new OneShotBehaviour() {
@Override
public void action() {
System.out.println("I am the first child Behaviour");
}
});
sb.addSubBehaviour(new SimpleBehaviour() {
boolean finished=false;
@Override
public void action() {
System.out.println("I am the second child Behaviour");
finished=true;
}
@Override
public boolean done() {
return finished;
}
});
sb.addSubBehaviour(new WakerBehaviour(this ,5000) {
@Override
protected void onWake() {
System.out.println("I am the third child Behaviour");
}
});
this.addBehaviour(sb);
}
}
输出:
I am the first child Behaviour
I am the second child Behaviour
I am the third child Behaviour
并发行为(ParallelBehaviour)
也是一个组合行为,其所有地子行为同时被激活。运行结果的可能标志如下:
(1)所有的子行为为运行结束;
(2)N个子行为运行结束:
(3)任何一个子行为运行结束。
构建ParallelBehaviour时需要设定行为的结束条件
ParallelBehaviour(Agent a,int endCondition){
super(a);
whenToStop=endCondition;
}
endCondition的取值可以是一个整数n,n表示行为个数,即若有n个行为运行完毕,则程序结束;也可以是ParallrlBehaviour.WHEN_ALL,表示所有行为运行结束则程序结束;也可以是ParallelBehaviour.WHEN_ANY,表示任意一个行为运行结束则程序结束。例如:
package MyFirstAgent;
import jade.core.Agent;
import jade.core.behaviours.OneShotBehaviour;
import jade.core.behaviours.ParallelBehaviour;
import jade.core.behaviours.SimpleBehaviour;
import jade.core.behaviours.WakerBehaviour;
public class MyparallAgent extends Agent {
@Override
protected void setup() {
ParallelBehaviour pb=new ParallelBehaviour(this ,ParallelBehaviour.WHEN_ALL);
pb.addSubBehaviour(new OneShotBehaviour() {
@Override
public void action() {
System.out.println("I am the first child Behaviour");
}
});
pb.addSubBehaviour(new SimpleBehaviour() {
boolean finished=false;
@Override
public void action() {
System.out.println("I am the third child Behaviour");
finished=true;
}
@Override
public boolean done() {
return finished;
}
});
pb.addSubBehaviour(new WakerBehaviour(this ,5000) {
@Override
protected void onWake() {
System.out.println("I am the second child Behaviour");
}
});
this.addBehaviour(pb);
}
}
输出:
I am the first child Behaviour
I am the third child Behaviour
I am the second child Behaviour
有限状态机行为(FSMBehaviour)
根据用户定义的有限状态机制执行它的子行为。每一个子行为都代表了有限状态机模型中的一个状态。也就是说,每个子类描述了一个FSM状态中要完成的动作,用户可以定义在FSM状态之间的转换。当一个对应于状态Si的子类完成后,它的终止值(由onEnd()方法返回)用来选择到活动状态的转换,这样就可以到达一个新的状态Sj。在下一个循环中,将会执行对应于Sj的子类。可以将某些FSMBehaviour类的子类注册为终止状态,任意一个代表终止状态的子类完成,FSMBehaviour行为就会终止。
定义一个FSMBehaviour至少需要下列几个步骤:
(1)调用registerFirstState()方法注册一个单一的行为作为有限状态机模型的初始状态;
(2)调用registerLastState()方法注册一个或多个行为作为有限状态机模型的终止状态;
(3)调用registerState()方法注册一个或多个行为作为有限状态机模型的中间状态;有两个参数:一个字符串参数,用于定义正在注册状态名称。一个Behaviour行为参数,表示在该状态下将被执行的行为。
(4)对于有限状态机的每一个状态,调用registerTransition()方法,注册该状态到另一个状态的变迁;有三个参数:两个字符串参数,分别表示转换的原状态和目标状态;一个整型参数,定义转换的标识。
(5)调用regisiterDefaultTransiton()方法注册从一个状态到另一个状态的无条件变迁。String[] 参数。这个参数描述了一个有限状态机状态集合,这些状态在注册转换发生时必须重置。
package MyFirstAgent;
import jade.core.Agent;
public class MyFSMAgent extends Agent {
@Override
protected void setup() {
this.addBehaviour(new MyFSMBehaviour(this));
}
}
package MyFirstAgent;
import jade.core.Agent;
import jade.core.behaviours.FSMBehaviour;
import jade.core.behaviours.OneShotBehaviour;
import javax.sound.midi.Soundbank;
public class MyFSMBehaviour extends FSMBehaviour {
public MyFSMBehaviour(Agent a) {
super(a);
this.registerFirstState(new OperationXBehaviour(),"X");
this.registerLastState(new OperationYBehaviour(),"Y");
this.registerState(new OperationZBehaviour(),"Z");
registerTransition("X","Y",1);
registerTransition("X","Z",0);
registerDefaultTransition("Z","X",new String[]{"X","Z"});
//准备第一个孩子执行,第一个孩子是注册为该FSMBehaviour的第一个状态的行为
this.scheduleFirst();
}
}
class OperationXBehaviour extends OneShotBehaviour {
private int numX;
@Override
public void action() {
numX=(int)(Math.random()*100+1);
System.out.println("本次产生了随机数:"+numX);
}
@Override
public int onEnd() {
return ((numX % 2 == 0)? 1 : 0 );
}
}
class OperationYBehaviour extends OneShotBehaviour {
@Override
public void action() {
System.out.println("Here is y");
}
}
class OperationZBehaviour extends OneShotBehaviour {
@Override
public void action() {
System.out.println("Here is z");
}
}
本次产生了随机数:47
Here is z
本次产生了随机数:33
Here is z
本次产生了随机数:14
Here is y
线程化行为
行为中的action()方法不会中断,以允许其他行为的加入。只有在当前正在运行的行为的action()方法返回后,才会考虑到下一个行为的调度。当一个行为需要执行阻塞操作时,不仅是阻塞了行为本身,实际上也阻塞了整个Agent的执行。任何JADE行为(简单或复合)都可作为一个线程化行为执行,通过jade.core.behaviours.ThreadedBehaviourFactory类提供的wrap()方法,可将一个普通的JADE行为打包成一个线程化行为。由addBehaviour()方法将它添加到指定Agent,即可实现在一个专用的线程中执行原来的行为对象。
import jade.core.*;
import jade.core.behaviours.*;
public class ThreadedAgent extends Agent{
private ThreadedBehaviourFactory tbf = new ThreadedBehaviourFactory();
protected void setup(){
Behaviour b = new OneShotBehaviour(this){
public void action(){
}
};
addBehaviour(tbf.wrap(b));
}
}
注意:
Agent类的removeBehaviour()方法不会对线程化行为产生影响。移除一个线程的行为首先要通过ThreadedBehaviourFactory类的getThread()找到其线程对象,然后调用该对象的interrupt()方法。