Agent运行命令解析:java jade.Boot [options] [AgentSpecifier list]
Options含义-container表明Agent运行时将启动一个外部容器,Agent生存在这个容器下,这个容器必须在主容器中注册-guiJADE的RMA图形界面将被打开-port指明主容器运行的端口号,缺省端口号为1099,知名端口号后,一台机器上可以启动多个主容器,例如java jade.Boot -gui -port 1088-container-name给容器命名。例如,第一次启动,输入:java jade.Boot -gui-container-name yuyu,则将主容器命名为yuyu,再打开一个命令窗口,输入java jade.Boot -gui-container-container-name haha,则将新启动的外围容器命名为haha-platform-id该选项为Agent平台命名,将默认的平台标识符命名为用户喜欢的标识符-name作用同-platform-id[AgentSpecifier list]定义启动的Agent列表,其中AgentSpecifier的形式为:AgentName:ClassName,ClassName中必须指出包名。可以启动多个Agent,每个Agent之间用;分隔。
Agent类的getAID()用来获取本地Agent的标识符。Agent标识符由全局唯一标识(GUID)和平台地址组成。GUID命名形式为< local-name >@< platform-name >。AID中包含的地址是 Agent所在平台的地址,这些地址在该agent与其他平台上的Agent通信时使用。 AID类提供了获取Agent本地名称、标识符、地址等一系列方法。如getLocalName()、getName()、getAllAddresses()
package MyFirstAgent; import jade.core.Agent; import java.util.Arrays; import java.util.Iterator; public class DemoAgent extends Agent { @Override protected void setup(){ System.out.println("AgentOne的AID:"+getAID()); System.out.println("AgentOne的local-name:"+getAID().getLocalName()); System.out.println("AgentOne的GUID:"+getAID().getName()); Iterator it=getAID().getAllAddresses(); while (it.hasNext()) { System.out.println("-"+it.next()); } } } 输出: E:\Develop\Java\jdk-12.0.2\bin\java.exe -Didea.launcher.port=2275 "-Didea.launcher.bin.path=E:\intellij idea2018\IntelliJ IDEA 2018.2.4\bin" -Dfile.encoding=UTF-8 -classpath "E:\学习笔记\yuguo\target\classes;E:\intellij idea2018\IntelliJ IDEA 2018.2.4\plugins\maven\repository\com\tilab\jade\jade\4.5.0\jade-4.5.0.jar;E:\intellij idea2018\IntelliJ IDEA 2018.2.4\plugins\maven\repository\commons-codec\commons-codec\1.3\commons-codec-1.3.jar;E:\intellij idea2018\IntelliJ IDEA 2018.2.4\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMainV2 jade.Boot -gui AgentOne:MyFirstAgent.DemoAgent 7月 04, 2020 3:55:04 下午 jade.core.Runtime beginContainer 信息: ---------------------------------- This is JADE 4.5.0 - revision 6825 of 23-05-2017 10:06:04 downloaded in Open Source, under LGPL restrictions, at http://jade.tilab.com/ ---------------------------------------- 7月 04, 2020 3:55:04 下午 jade.imtp.leap.LEAPIMTPManager initialize 信息: Listening for intra-platform commands on address: - jicp://172.168.1.142:1099 7月 04, 2020 3:55:05 下午 jade.core.BaseService init 信息: Service jade.core.management.AgentManagement initialized 7月 04, 2020 3:55:05 下午 jade.core.BaseService init 信息: Service jade.core.messaging.Messaging initialized 7月 04, 2020 3:55:05 下午 jade.core.BaseService init 信息: Service jade.core.resource.ResourceManagement initialized 7月 04, 2020 3:55:05 下午 jade.core.BaseService init 信息: Service jade.core.mobility.AgentMobility initialized 7月 04, 2020 3:55:05 下午 jade.core.BaseService init 信息: Service jade.core.event.Notification initialized 7月 04, 2020 3:55:05 下午 jade.mtp.http.HTTPServer <init> 信息: HTTP-MTP Using XML parser com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser 7月 04, 2020 3:55:05 下午 jade.core.messaging.MessagingService boot 信息: MTP addresses: http://PC-20191102IUIM:7778/acc 7月 04, 2020 3:55:05 下午 jade.core.AgentContainerImpl joinPlatform 信息: -------------------------------------- Agent container Main-Container@172.168.1.142 is ready. -------------------------------------------- AgentOne的AID:( agent-identifier :name AgentOne@172.168.1.142:1099/JADE :addresses (sequence http://PC-20191102IUIM:7778/acc )) AgentOne的local-name:AgentOne AgentOne的GUID:AgentOne@172.168.1.142:1099/JADE -http://PC-20191102IUIM:7778/acc通过以下的方式获得已知本地名称Agent的AID:
String localname = "Peter"; AID id =new AID (localname,AID.ISLOCALNAME);类似的已知Agent的GUID后,我们可以用如下的方式获得其AID
String guid = "Peter@foo-platform"; AID id = new AID(guid,AID.ISGUID);可以向Agent传递参数:
System.out.println("My arguments are:"); Object[] args = getArguments(); if (args!=null){ for (int i = 0; i < args.length; i++) { System.out.println("-"+args[i]); } }Agent终止:
takeDown()方法清理,doDelete()终止
setup()方法执行后,Agent就在AMS中注册成功。它的实际工作任务通常在所添加的行为Behaviour中执行,也就是说,一个活动的Agent相当于一个完成任务的主体,而真正的任务载体时Behaviour类的实例。 每一个Behaviour都是jade.core.behaviours.Behaviours类的子类,一个Behaviour可以嵌套另一个Behaviour。在Agent生命周期的任何时刻都可以调用Behaviour执行某种任务,方法是使用Agent类的addBehaviout(Behaviour)方法。而且要实现两个抽象方法:action()和done()在action()中定义Agent需要实现的任务;done()方法返回一个布尔值来判断这个Behaviour是否完成其任务,是否应该将其移出其所在的Agent所管理的行为队列,每个Agent可与i并行执行多个Behaviour。 编写一个FirstBehaviour类,将类添加到Agent的行为队列中
package MyFirstAgent; import jade.core.behaviours.Behaviour; public class FirstBehaviour extends Behaviour { private int numA=5; @Override public boolean done() { return true; } @Override public void action() { if ((numA%2)!=0){ System.out.println("numA is an odd number"); } else { System.out.println("numA is an even number"); } } } package MyFirstAgent; import jade.core.Agent; import java.util.Arrays; import java.util.Iterator; public class DemoAgent extends Agent { @Override protected void setup(){ //添加行为 this.addBehaviour(new FirstBehaviour()); } }JADE中的Agent之间的通信基于异步通信模式。 每一个JADE Agent都有一个邮箱,即Agent消息队列,其他Agent发送来的信息都投入到这个邮箱中。一旦邮箱中收到消息,系统会给Agent发出通知,由程序元编写程序让Agent有选择地处理消息。 遵循FIPA规范,JADE Agent之间地通信所交换地是ACL消息,每一条消息都是继承了JADE.lang.acl.ACLMessage类的一个对象,包含了由FIPA规范制定的一系列消息属性,主要消息域如下:
消息的发送者;消息接收者列表;消息原语,如REQUEST原语表示发送方请求接收方执行某种操作;消息的具体内容;用来表达消息内容的语言,如English;用来说明消息内容中某些词汇或短语的本体Ontology;其他。 准备发送消息的Agent应该创建一个新的ACLMessage对象,给他的属性赋予适当的值,然后调用Agent.send()方法发送消息。同样地,一个准备接收消息的Agent可以调用receive()或者blockingReceive()方法接收消息。发送消息就是填写好ACLMessage对象的各个域,然后调用Agent类的send()方法。 本例中让DemoAgent类的一个Agent实例作为信息发送方,让他向另一个运行时名字为alice的Agent发送信息,通知Alice明天考试。
编写一个发送消息的行为类,在Behaviour类的子类SendBehaviour中编写发送消息的代码,而发送消息的send()方法的主体是Agent,而不是Behaviour,需要在SendBehaviour的构造函数中将SengBehaviour与DemoAgent类关联起来。 package MyFirstAgent; import jade.core.AID; import jade.core.behaviours.Behaviour; import jade.lang.acl.ACLMessage; public class SendBehaviour extends Behaviour { private DemoAgent sendagent=null; @Override public void action() { ACLMessage msg=new ACLMessage(ACLMessage.INFORM); msg.addReceiver(new AID("Alice",AID.ISLOCALNAME)); msg.setLanguage("English"); msg.setContent("There will be an examination tomorrow"); sendagent.send(msg); } @Override public boolean done() { return true; } public SendBehaviour(DemoAgent a){ sendagent=a; } } 修改setup()方法,添加SendBehaviour package MyFirstAgent; import jade.core.Agent; import java.util.Arrays; import java.util.Iterator; public class DemoAgent extends Agent { @Override protected void setup(){ this.addBehaviour(new SendBehaviour(this)); } }由于运行时,Agent的实例在时刻监听发送给它的消息,一次性行为不适合处理消息的实时接收,所以,在消息接收时,我们使用了可以处理循环操作的特殊的Behaviour类:CyclicBehaviour
package MyFirstAgent; import jade.core.Agent; import jade.core.behaviours.Behaviour; import jade.core.behaviours.CyclicBehaviour; import jade.lang.acl.ACLMessage; public class DemoAgentSecond extends Agent { @Override protected void setup() { Behaviour loop=new CyclicBehaviour() { @Override public void action() { ACLMessage msg=receive(); if(msg!=null){ System.out.println("I received this message:"+msg.getContent()); } } }; this.addBehaviour(loop); } }从代码的形式上看是写在同一个文件中,但实际上编译的时候仍会产生两个.class文件,一个对应Agent,一个对应CyclicBehaviour。 同时运行两个Agent输出:
I received this message:There will be an examination tomorrow