• JADE提升篇


    以下如果未特殊声明,都在JADE管理器中运行,然后再Eclipse控制台中查看!
    JADE行为类
    在前面的例子中,Agent所作的工作都定义在了setup方法中,实际上它具有的行为和执行的动作都应该定义在Behavious类中,我们可以对Behavior类生成实例,然后将任务或者动作代码放在对Behavious类中的action方法中,action方法是必须要有的。Behavious类还有很多子类,分别对应着不同类型的Behaviour,包括SimpleBehaviour,SequencesBehaviour, ParallelBehavior, CyclicBehavior等。
    一个Agent的行为表示它能够执行的任务,通过继承jade.core.behaviours.Behaviour来实现。然后在Agent类中通过addBehaviour()方法将行为加入进来。当一个Agent启动(通过setup()方法后,行为可以在任何时间加入进来。
    要定义Behaviour必须实现其action()方法,它定义了Agent的执行时的实际动作,而done()方法指名了一个行为是否已执行完毕,是否要从行为池中删除。
    一个Agent可以并发执行多个behaviour。每个Agent线程启动后执行的过程如下:

    wpsC75A.tmp

    SimpleBehaviour简单行为

    下面的例子中我们不在setup()中打印信息,而是把它放在一个简单行为中:
    在jadetest包里面新建一个java类命名为HelloWorldBehaviour,输入下面代码。配置中把变量改为-gui sb:jadetest.SimpleBehaviour,运行

    package jadetest;
    
    /** 
     * @function 
     * @author Jacksile E-mail:tufujietec@foxmail.com 
     * @date 2016年1月14日 下午5:20:11 
     */
    import jade.core.Agent;
    import jade.core.Location;
    import jade.core.behaviours.SimpleBehaviour;
    
    public class HelloWorldBehaviours extends Agent {
        public void setup() {
            SimpleBehaviour hello_behaviour = new SimpleBehaviour(this) {
                boolean finished = false;
    
                // 覆盖 Behaviour 类的action这一抽象方法
                public void action() {
                    System.out.println("HelloWorldBehaviour run: Hello World!");
                    System.out.println("-----About Me:-----");
                    System.out.println("My local name is:" + getLocalName());
                    System.out.println("My globally unique name is:" + getName());
                    System.out.println("-----About Here:-----");
                    Location l = here();
                    System.out.println("I am running in a location called:" + l.getName());
                    System.out.println("Which is identified uniquely as:" + l.getID());
                    System.out.println("And is contactable at:" + l.getAddress());
                    System.out.println("Using the protocol:" + l.getProtocol());
                    finished = true;
                }
    
                // done()在父类中也是一个抽象方法
                public boolean done() {
                    return finished;
                }
            };
            addBehaviour(hello_behaviour);
        } // setup()
    }

    然后使用智能体管理器添加智能体并运行:

    wps804C.tmp

    wps804D.tmp

    输出结果为:
    HelloWorldBehaviour run: Hello World!
    -----About Me:-----
    My local name is:hwb
    My globally unique name is:hwb@172.17.98.217:1099/JADE
    -----About Here:-----
    I am running in a location called:Main-Container
    Which is identified uniquely as:Main-Container@172.17.98.217
    And is contactable at:172.17.98.217
    Using the protocol:jicp
    这个程序相较于前面的例子多了action, done两个函数,它们分别执行自己的操作。HelloWorldBehaviours类加载时定义一个简单行为,这个简单行为执行的操作由action,done来实现。然后,再通过加载语句(addBehaviour(hello_behaviour))执行这个简单行为

    简单行为和循环行为(CyclicBehaviour)组合的例子

    一个Agent中可以加入各种Behaviour构成CompositeBehaviour。
    在Eclipse的jade工程中编写下列程序,过程如前所描述。

    package jadetest;
    
    /** 
     * @function 
     * @author Jacksile E-mail:tufujietec@foxmail.com 
     * @date 2016年1月14日 下午8:46:29 
     */
    import jade.core.Agent;
    import jade.core.behaviours.Behaviour;
    import jade.core.behaviours.CyclicBehaviour;
    import jade.core.behaviours.OneShotBehaviour;
    
    public class SimpleAgent extends Agent {
        private class FourStepBehaviour extends Behaviour {
            // SimpleBehaviour hello_behaviour = new SimpleBehaviour(this){
            // 这两条语句有很大不同吗?上面的定义一个新的类,下面的修改了标准行为的执行内容
            private int step = 1;
    
            public void action() {
                switch (step) {
                case 1:
                    System.out.println("Operation 1");
                    break;
                case 2:
                    System.out.println("Operation 2. Adding one-shot behaviour");
                    myAgent.addBehaviour(new OneShotBehaviour(myAgent) {
                        // 增加了一个新的动作,即快照
                        public void action() {
                            System.out.println("One-shot");
                        }
                    });// myAgent.addbehaviour
                    break;
                case 3:
                    System.out.println("Operation 3");
                    break;
                case 4:
                    System.out.println("Operation 4");
                    break;
                }// switch
                step++;
            } // action
    
            public boolean done() {
                return step == 5; // 判断语句
            }
    
            public int onEnd() {
                myAgent.doDelete();
                System.out.println("Finished!");
                return super.onEnd();
            }
        } // class FourStepBehaviour
    
        /** Creates a new instance of SimpleAgent */
        protected void setup() {
            System.out.println("Agent " + getLocalName() + " started.");
            addBehaviour(new CyclicBehaviour(this) { // 增加了一个循环行为
                public void action() {
                    System.out.println("Cycling");
                }
            }); // //增加的循环行为
            // Add the generic behaviour
            addBehaviour(new FourStepBehaviour());
        }// //setup()
    }

    输出结果:
    Agent sa started.
    Cycling
    Operation 1
    Cycling
    Operation 2. Adding one-shot behaviour
    Cycling
    Operation 3
    One-shot
    Cycling
    Operation 4
    Finished!
    注意每个Agent内部都有一个ParallelBehaviour,我们如果加入多个behaviour到Agent中,他们会并行执行。behaviours加入到队列的顺序就是他们执行的次序。最后,behaviours可以动态的加入到Agent以及CompositeBehaviour。
    总结:每个主体的执行都是从setup() 开始顺序执行的。主体可以执行自定义的行为,如上例中的hello_behaviour ,FourStepBehaviour,也可以执行标准化的行为如OneShotBehaviour。
    Agent通讯:ACL(Agent communication language)
    JADE的Agent之间进行通信使用的acl语言遵循fipa acl规范。一个acl消息通常包含这些参数:sender:消息的发送者,用Agent标志AID表示; receivers,接受Agent消息的Agent可以是多个;Reply-to,应收到回应的接受者;Performative:标志发送消息的目的,即发送者想要通过发送消息干什么,通常有这样一些常值:REQUEST, INFORM, ACCEPT_PROPOSAL, REJECT_PROPOSAL, PROPOSE;Content,消息的内容;内容语言,比如内容的编码格式;ontology,双方都能够理解的消息内容的概念说明和语义描述。
    简单实例
    发送者:

    package jadetest;
    
    /** 
     * @function 
     * @author Jacksile E-mail:tufujietec@foxmail.com 
     * @date 2016年1月14日 下午9:00:25 
     */
    import jade.core.AID;
    import jade.core.Agent;
    import jade.core.behaviours.Behaviour;
    import jade.lang.acl.ACLMessage;
    
    public class SimpleSender extends Agent {
        protected void setup() {
            addBehaviour(new Behaviour(this) {
                private boolean finished = false;
    
                public void action() {
                    System.out.println(getLocalName() + ": about to inform bob hello");
                    // we sleep here to give bob a chance to start.
                    doWait(5000);
                    AID r = new AID();// 作用是什么?表示消息的发送者
                    r.setLocalName("bob");
                    ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
                    // set performative
                    msg.setSender(getAID());
                    msg.addReceiver(r);
                    msg.setContent("Hello_BOB");
                    send(msg);
                    System.out.println(getLocalName() + ": Send hello to bob");
                    System.out.println("the content is:" + msg.getContent()); // finished = true;
                    doWait(5000);
                    doDelete();
                } // action
    
                public boolean done() {
                    return finished;
                }
            }); // addbehavior
        }// setup
    }// Agent

    这段代码的主要执行过程为:构建一个AID,以此来指出该消息的目的Agent。这里我们指定目的为一个本地的Agent,名字为bob。建立一个ACL消息标志其performative为INFORM。设定Sender为自身,指定接收者为bob。然后发送消息内容。打印相关信息。
    接收者:他的名字必须为bob

    package jadetest;
    
    /** 
     * @function 
     * @author Jacksile E-mail:tufujietec@foxmail.com 
     * @date 2016年1月14日 下午9:01:36 
     */
    import jade.core.Agent;
    import jade.core.behaviours.SimpleBehaviour;
    import jade.lang.acl.ACLMessage;
    
    public class SimpleReceiver extends Agent {
        class DoSimpleReceiveBehaviour extends SimpleBehaviour {
            private boolean finished = false;
    
            public DoSimpleReceiveBehaviour(Agent Agent) {
                super(Agent);
            }
    
            public void action() {
                ACLMessage msg = receive();
                if (msg != null) {
                    System.out.println(getLocalName() + ": received the following message : ");
                    System.out.println(msg.toString());
                    finished = true;
                    myAgent.doDelete();
                } else {
                    System.out.println(getLocalName()
                            + ":No message received, Blocking the behaviour till one is");
                    block();
                }
            }// action
    
            public boolean done() {
                return finished;
            }
        }// DoSimpleReceiveBehaviour
    
        protected void setup() {
            DoSimpleReceiveBehaviour behaviour = new DoSimpleReceiveBehaviour(this);
            addBehaviour(behaviour);
        }
    }// Agent

    接收者的代码流程为:添加一个简单行为,这一行为检查现在是否有受到消息,若没有,则执行block()方法组织目前的behaviour执行,直到有新的消息到达。
    复杂实例
    FIPA定义了一组交互协议,包括FIPA-request, FIPA-query, FIPA-request-when, FIPA-contract-net, FIPA-Iterater-net, FIPA-Auction-English, FIPA-Auction-Dutch.其中:
    REQUEST-INFORM:A请求B做一些工作,B可以同意或拒绝。如果B同意,则会去完成并告诉A该工作已经完成。等等。
    Query:A想知道一些事情,B可以同意或不同意,并将B的回应告诉A。
    Propose:在给定一些precondition的条件下,提出一个proposal去执行某些动作。
    在Eclipse中创建文件夹ips:其代码文件有两个,分别为

    package ips;
    
    /** 
     * @function 
     * @author Jacksile E-mail:tufujietec@foxmail.com 
     * @date 2016年1月14日 下午9:03:05 
     */
    import jade.core.AID;
    import jade.core.Agent;
    import jade.domain.FIPANames.InteractionProtocol;
    import jade.lang.acl.ACLMessage;
    import jade.proto.SimpleAchieveREInitiator;
    
    public class SimpleRequestInitiator extends Agent {
        static class MarriageProposer extends SimpleAchieveREInitiator {
            protected MarriageProposer(Agent Agent, ACLMessage msg) {
                super(Agent, msg);
            }
    
            protected void handleAgree(ACLMessage msg) {
                System.out.println(myAgent.getLocalName() + ": 吼吼! " + msg.getSender().getLocalName()
                        + " 已经同意嫁给我了, I'm so excited!");
            }
    
            protected void handleRefuse(ACLMessage msg) {
                System.out.println(myAgent.getLocalName() + ": Oh no! "
                        + msg.getSender().getLocalName() + " 拒绝了我, i feel sad.");
            }
    
            protected void handleInform(ACLMessage msg) {
                System.out.println(myAgent.getLocalName() + ":" + msg.getSender().getLocalName()
                        + " has informed me of the status of my request." + " They said : "
                        + msg.getContent());
            }
    
            protected void handleNotUnderstood(ACLMessage msg) {
                System.out.println(myAgent.getLocalName() + ":" + msg.getSender().getLocalName()
                        + " has indicated that they didn't understand.");
            }
    
            protected void handleOutOfSequence(ACLMessage msg) {
                System.out.println(myAgent.getLocalName() + ":" + msg.getSender().getLocalName()
                        + "has sent me a message which I wasn't" + " expecting in this conversation");
            }
        }
    
        protected void setup() {
            System.out.println(getLocalName() + ": about to propose marriage to bob ");
            doWait(5000); // wait for bob to be started.
            ACLMessage msg = new ACLMessage(ACLMessage.REQUEST);
            AID to = new AID();
    
            to.setLocalName("bob");
            msg.setSender(getAID());
            msg.addReceiver(to);
            msg.setContent("Marry Me!");
            msg.setProtocol(InteractionProtocol.FIPA_REQUEST);
            addBehaviour(new MarriageProposer(this, msg));
        }
    }

    还有:

    package ips;
    
    /** 
     * @function 
     * @author Jacksile E-mail:tufujietec@foxmail.com 
     * @date 2016年1月14日 下午9:03:57 
     */
    
    import jade.core.AID;
    import jade.core.Agent;
    import jade.domain.FIPANames.InteractionProtocol;
    import jade.lang.acl.ACLMessage;
    import jade.proto.SimpleAchieveREResponder;
    
    public class SimpleRequestResponder extends Agent {
        static class MarriageResponder extends SimpleAchieveREResponder {
            public MarriageResponder(Agent Agent) {
                super(Agent, createMessageTemplate(InteractionProtocol.FIPA_REQUEST));
            }
    
            protected ACLMessage prepareResponse(ACLMessage msg) {
                ACLMessage response = msg.createReply();
                if (msg.getContent() != null && msg.getContent().equals("Marry Me!")) {
                    System.out.println(myAgent.getLocalName() + ":" + msg.getSender().getLocalName()
                            + " has asked me to marry him!");
                    AID sender;
                    sender = msg.getSender();
                    if (sender.getLocalName().equals("baz")) {
                        response.setPerformative(ACLMessage.AGREE);
                        System.out.println(myAgent.getLocalName() + ":I'm going to agree.");
                    } else {
                        response.setPerformative(ACLMessage.REFUSE);
                        System.out.println(myAgent.getLocalName() + ":I'm going to turn him down.");
                    }
                } else {
                    response.setPerformative(ACLMessage.NOT_UNDERSTOOD);
                    System.out.println(myAgent.getLocalName() + ":I didn't understand what "
                            + msg.getSender().getLocalName() + " just said to me.");
                }
                return response;
            }
    
            protected ACLMessage prepareResultNotification(ACLMessage inmsg, ACLMessage outmsg) {
                // what they have asked is now complete (or if it failed)
                ACLMessage msg = inmsg.createReply();
                msg.setPerformative(ACLMessage.INFORM);
                msg.setContent("I Do!");
                return msg;
            }
        }
    
        protected void setup() {
            System.out.println(getLocalName() + ": I wonder if anybody wants to marry me?");
            addBehaviour(new MarriageResponder(this));
        }//
    }

    按照以前记载,先打开GUI管理器,主类依然为jade.Boot,参数为-gui,GUI管理打开之后先建立一个名为bob的Agent,对应的类为ips.SimpleRequestResponder,然后再建立一个名为baz的Agent,对应的类为ips.SimpleRequestInitiator,记住顺序不能变,以下是输出结果:
    bob: I wonder if anybody wants to marry me?
    baz: about to propose marriage to bob
    bob:baz has asked me to marry him!
    bob:I'm going to agree.
    baz: 吼吼! bob 已经同意嫁给我了, I'm so excited!
    baz:bob has informed me of the status of my request. They said : I Do!
    上例中,应用了SimpleAchieveREInitiator和SimpleAchieveREResponder两个基类,适用于两个Agent之间的交互。可以看出发起者对于不同的回应有不同的执行动作。
    技巧:从AMS中获取所有Agent的AID。

    package ips;
    
    /** 
     * @function 
     * @author Jacksile E-mail:tufujietec@foxmail.com 
     * @date 2016年1月16日 下午1:52:33 
     */
    import jade.core.Agent;
    import jade.domain.AMSService;
    import jade.domain.FIPAAgentManagement.AMSAgentDescription;
    import jade.domain.FIPAAgentManagement.SearchConstraints;
    import jade.lang.acl.ACLMessage;
    
    public class AMSDump extends Agent {
        protected void setup() {
            AMSAgentDescription[] Agents = null;
            try {
                SearchConstraints c = new SearchConstraints();
                c.setMaxResults(new Long(-1));
                Agents = AMSService.search(this, new AMSAgentDescription(), c);
            } catch (Exception e) {
                System.out.println("Problem searching AMS: " + e);
                e.printStackTrace();
            }
    
            ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
            msg.setContent("Ping");
            for (int i = 0; i < Agents.length; i++) {
                if (Agents[i].getName().equals(getAID())) {
                    // 如果不是自己则加入到接收者数组中
                    continue;
                }
                msg.addReceiver(Agents[i].getName());
            }
        }
    }

    ACL高级特性之消息模板:

    MessageTemplate class 利用MessageTemplate可以针对ACLMessage的每个属性设置模式,以达到过滤消息的目的。为了可以构建更复杂的匹配规则,多个模式也可以进行and,or,not运算。最有用的一些规则或方法包括:通信行为匹配,发送者匹配,会话ID匹配。
    比如MatchPerformative( performative ) 是通信行为的匹配。
    这里 performative 可能是:
    ACLMessage.INFORM
    ACLMessage.PROPOSE
    ACLMessage.AGREE
    还有发送者匹配MatchSender( AID ),会话匹配MatchConversationID( String ),通信协议匹配MatchProtocol( String ) ,本体匹配MatchOntology( String)。
        比如:MessageTemplate mt = MessageTemplate.and( 
                   MessageTemplate.MatchPerformative( ACLMessage.INFORM ),
                   MessageTemplate.MatchSender( new AID( "a1",                                                         AID.ISLOCALNAME))) ;
    相当于建立了一个模板,表示消息规则为INFORM行为并且发送者为“a1”。
    接收过程如下:ACLMessage msg = receive( mt );
                 if (msg != null) { ... handle message }
                 block();
    示例:

    package jadePrime.acl;
    
    /** 
     * @function 
     * @author Jacksile E-mail:tufujietec@foxmail.com 
     * @date 2016年1月14日 下午9:07:11 
     */
    import jade.core.AID;
    import jade.core.Agent;
    import jade.core.behaviours.CyclicBehaviour;
    import jade.lang.acl.ACLMessage;
    import jade.lang.acl.MessageTemplate;
    
    public class Template extends Agent {
        MessageTemplate mt1 = MessageTemplate.and(MessageTemplate.MatchPerformative(ACLMessage.INFORM),
                MessageTemplate.MatchSender(new AID("a1", AID.ISLOCALNAME)));
    
        protected void setup() {
            // Send messages to "a1" and "a2"
    
            ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
            msg.setContent("Ping");
            for (int i = 1; i <= 2; i++)
                msg.addReceiver(new AID("a" + i, AID.ISLOCALNAME));
    
            send(msg);
    
            // Set-up Behaviour 1
    
            addBehaviour(new CyclicBehaviour(this) {
                public void action() {
                    System.out.print("Behaviour ONE: ");
                    ACLMessage msg = receive(mt1);
                    if (msg != null)
                        System.out.println("gets " + msg.getPerformative() + " from "
                                + msg.getSender().getLocalName() + "=" + msg.getContent());
                    else
                        System.out.println("gets NULL");
                    block();
                }
            });
            // Set-up Behaviour 2
            addBehaviour(new CyclicBehaviour(this) {
                public void action() {
                    System.out.print("Behaviour TWO: ");
                    ACLMessage msg = receive();
                    if (msg != null)
                        System.out.println("gets " + msg.getPerformative() + " from "
                                + msg.getSender().getLocalName() + "=" + msg.getContent());
                    else
                        System.out.println("gets NULL");
                    block();
                }
            });
        }
    }
    package jadePrime.acl;
    
    /** 
     * @function 
     * @author Jacksile E-mail:tufujietec@foxmail.com 
     * @date 2016年1月14日 下午9:10:07 
     */
    import jade.core.Agent;
    import jade.core.behaviours.CyclicBehaviour;
    import jade.lang.acl.ACLMessage;
    
    public class Responder extends Agent {
        protected void setup() {
            addBehaviour(new CyclicBehaviour(this) {
                public void action() {
                    ACLMessage msg = receive();
                    if (msg != null) {
    
                        ACLMessage reply = msg.createReply();
                        reply.setPerformative(ACLMessage.INFORM);
                        reply.setContent(" Gossip.....");
                        send(reply);
    
                        reply.setPerformative(ACLMessage.PROPOSE);
                        reply.setContent(" Really sexy stuff... cheap! ");
                        send(reply);
                    }
                    block();
                }
            });
        }
    }

    输出结果:
    Behaviour ONE: gets NULL
    Behaviour TWO: gets 6 from ams=( (action ( agent-identifier :name template@192.168.23.1:1099/JADE  :addresses (sequence http://jacksile:7778/acc )) (ACLMessage) ) (MTS-error ( agent-identifier :name a1@192.168.23.1:1099/JADE ) (internal-error "Agent not found: getContainerID() failed to find agent a1@192.168.23.1:1099/JADE")) )
    Behaviour ONE: gets NULL

    Base64:发送消息为java序列化对象

    在JADE中,支持Agents之间通信的消息内容使用序列化的java对象,对本地应用,特别是所有Agent都用java实现的情况下也是很有用的.
    看实例:一个ObjectSender负责发送一个Person对象,ObjectReceiver负责接收后打印出接收到的内容。
    源文件:Person.java

    package examples.Base64;
    
    /** 
     * @function 
     * @author Jacksile E-mail:tufujietec@foxmail.com 
     * @date 2016年1月15日 下午12:34:47 
     */
    import java.io.Serializable;
    import java.util.Date;
    
    public class Person implements Serializable {
        String name;
        String surname;
        Date birthdate;
        int age;
    
        Person(String n, String s, Date d, int a) {
            name = n;
            surname = s;
            birthdate = d;
            age = a;
        }
    
        public String toString() {
            return (name + " " + surname + " born on " + birthdate.toString() + " age = " + age);
        }
    }

    文件2:ObjectSender.java

    package examples.Base64;
    
    /** 
     * @function 
     * @author Jacksile E-mail:tufujietec@foxmail.com 
     * @date 2016年1月15日 下午12:35:47 
     */
    import jade.core.AID;
    import jade.core.Agent;
    import jade.lang.acl.ACLMessage;
    
    import java.io.IOException;
    import java.util.Date;
    
    public class ObjectSender extends Agent {
        protected void setup() {
    
            try {
                ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
                msg.setContent("Ping");
    
                AID personR = new AID("personR", AID.ISLOCALNAME);
                msg.addReceiver(personR);
                Person p = new Person("Name1", "Surname1", new Date(), 1);
                msg.setContentObject(p);
                msg.setLanguage("JavaSerialization");
                send(msg);
                System.out.println(getLocalName() + " sent 1st msg " + msg);
    
                send(msg);
    
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            doDelete(); // kill itself because it has completed its task.
    
        }
    
    }

    文件三:ObjectReceiver.java

    package examples.Base64;
    
    /** 
     * @function 
     * @author Jacksile E-mail:tufujietec@foxmail.com 
     * @date 2016年1月15日 下午12:37:17 
     */
    import jade.core.Agent;
    import jade.core.behaviours.CyclicBehaviour;
    import jade.lang.acl.ACLMessage;
    import jade.lang.acl.UnreadableException;
    
    public class ObjectReceiver extends Agent {
        protected void setup() {
            addBehaviour(new CyclicBehaviour(this) {
                public void action() {
                    try {
                        ACLMessage msg = blockingReceive();
                        System.out.println(getLocalName() + " rx msg" + msg);
                        if ("JavaSerialization".equals(msg.getLanguage())) {
                            Person p = (Person) msg.getContentObject();
                            System.out.println(getLocalName() + " 获取Java对象: ");
                            System.out.println(p.getClass().getName());
                            System.out.println(p.toString());
                        }
                    } catch (UnreadableException e3) {
                        System.err.println(getLocalName() + " catched exception " + e3.getMessage());
                    }
    
                    block();
                }
            });
        }
    
    }

    外部应用程序调用Agent
    JADE2.3以后的版本都提供了in-process接口来实现外部应用程序对Agent的调用。
    我们可以通过jade.core.Runtime.instance()来获得jade运行时的一个单独得实例。有两种方法可以用来创建一个jade主容器和一个jade远程容器。主要调用过程如下:

    wpsC4FA.tmp

    先看简单的例子:

    package inprocess;
    
    /** 
     * @function 
     * @author Jacksile E-mail:tufujietec@foxmail.com 
     * @date 2016年1月15日 下午12:48:37 
     */
    import jade.core.Agent;
    import jade.core.behaviours.SimpleBehaviour;
    
    /**
     *
     * @author Administrator
     */
    public class CustomAgent extends Agent {
    
        public void setup() {
            SimpleBehaviour helloBehaviour = new SimpleBehaviour(this) {
                boolean finished = false;
    
                public void action() {
                    System.out.println("Hello World Behaviour run: 你好,世界!");
                    System.out.println("-----我是:-----");
                    System.out.println("我的本地名称是:" + getLocalName());
                    System.out.println("我全局唯一的标志名称为:" + getName());
                    finished = true;
                }
    
                public boolean done() {
                    return finished;
                }
    
            };
            addBehaviour(helloBehaviour);
        }
    
    }

    以上是要调用的Agent类

    package inprocess;
    
    /** 
     * @function 
     * @author Jacksile E-mail:tufujietec@foxmail.com 
     * @date 2016年1月15日 下午12:49:43 
     */
    
    import jade.core.Profile;
    import jade.core.ProfileImpl;
    import jade.core.Runtime;
    import jade.wrapper.AgentContainer;
    import jade.wrapper.AgentController;
    
    public class InprocessTest {
    
        public static void main(String args[]) {
            try {
                Runtime rt = Runtime.instance();
                rt.setCloseVM(true);
                Profile pMain = new ProfileImpl(null, 8888, null);
                System.out.println("Launching a whole in-process platform..." + pMain);
                AgentContainer mc = rt.createMainContainer(pMain);
                // set now the default Profile to start a container
                ProfileImpl pContainer = new ProfileImpl(null, 8888, null);
                System.out.println("Launching the Agent container ..." + pContainer);
                AgentController custom = mc.createNewAgent("custom", "inprocess.CustomAgent", null);
                custom.start();
    
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    }// 以上是调用者,在Eclipse中调试通过。

    再看一个例子,也是main函数中动态创建Agent的例子。可以通过先创建另一个容器,然后再这个容器中创建Aent。比如:

    public static void main(String[] args) {
            // TODO code application logic here
            Runtime rt = Runtime.instance();
            rt.setCloseVM(true);
            ContainerController cc =  rt.createAgentContainer(new ProfileImpl(false));
            
            AgentController pingAgent = null;
            try    {
                // create Agent and start it
                (cc.createNewAgent("hello", "jadeclient.HelloWorldAgent", new Object[0])).start();
            } catch (Exception e){}
        }

    可以写如下测试程序,这里用Eclipse平台,一个HelloWorldAgent,他将被动态创建并向主容器中的server发送一个消息:

    package jadeclient;
    
    /** 
     * @function 
     * @author Jacksile E-mail:tufujietec@foxmail.com 
     * @date 2016年1月15日 下午12:50:50 
     */
    import jade.core.AID;
    import jade.core.Agent;
    import jade.core.behaviours.SimpleBehaviour;
    import jade.lang.acl.ACLMessage;
    
    public class HelloWorldAgent extends Agent {
        public void setup() {
    
            addBehaviour(new SimpleBehaviour(this) {
                boolean finished = false;
                AID server = new AID("server", AID.ISLOCALNAME);
    
                public void action() {
                    System.out.println("我的本地名称是:" + getLocalName());
                    ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
                    msg.setContent("消息内容");
                    msg.addReceiver(server);
                    send(msg);
                    System.out.println("已经往主容器中的server发送信息#");
                    block(1000);
    
                    finished = true;
                }
    
                public boolean done() {
                    return finished;
                }
            });
        };
    }

    而server角色是收到消息后打印出来。

    /*
     * ReceiverAgent.java
     * To change this template, choose Tools | Template Manager
     * and open the template in the editor.
     */
    
    package jadeclient;
    
    /** 
     * @function 
     * @author Jacksile E-mail:tufujietec@foxmail.com 
     * @date 2016年1月15日 下午12:51:57 
     */
    import jade.core.Agent;
    import jade.core.behaviours.CyclicBehaviour;
    import jade.lang.acl.ACLMessage;
    
    /**
     *
     * @author admin
     */
    public class ReceiverAgent extends Agent {
    
        /** Creates a new instance of ReceiverAgent */
    
        // 把接收到的信息打印出来
        protected void setup() {
            addBehaviour(new CyclicBehaviour(this) {
                public void action() {
                    ACLMessage msg = receive();
                    if (msg != null)
                        System.out
                                .println("收到信息 " + myAgent.getLocalName() + " <- " + msg.getContent());
                    block();
                }
            });
        }
    
    }

    所有类写完之后,这里运行的时候先打开GUI管理器,然后GUI界面下创建一个名叫server的Agent,其类为jadeclient. ReceiverAgent,然后再创建一个名叫hello的Agent,其类为jadeclient.HelloWorldAgent.,记住,顺序不能变
    在GUI界面管理器显示如下,在Eclipse平台中下面显示的是打印出的信息,可见在同一主机的不同容器中Agent通信与在同一容器中通信并无二样。

    wps3655.tmp

    wps3665.tmp

    看一个稍微复杂的例子:

    package examples.inprocess;
    
    /** 
     * @function 
     * @author Jacksile E-mail:tufujietec@foxmail.com 
     * @date 2016年1月15日 下午12:53:06 
     */
    
    import jade.core.Profile;
    import jade.core.ProfileImpl;
    import jade.core.Runtime;
    import jade.core.behaviours.CyclicBehaviour;
    import jade.wrapper.AgentContainer;
    import jade.wrapper.AgentController;
    
    public class InProcessTest {
    
        // Simple class behaving as a Condition Variable
        public static class CondVar {
            private boolean value = false;
    
            synchronized void waitOn() throws InterruptedException {
                while (!value) {
                    wait();
                }
            }
    
            synchronized void signal() {
                value = true;
                notifyAll();
            }
    
        } // End of CondVar class
    
        // This class is a custom Agent, accepting an Object through the
        // object-to-Agent communication channel, and displying it on the
        // standard output.
        public static class CustomAgent extends jade.core.Agent {
    
            public void setup() {
                // Accept objects through the object-to-Agent communication
                // channel, with a maximum size of 10 queued objects
                setEnabledO2ACommunication(true, 10);
    
                // Notify blocked threads that the Agent is ready and that
                // object-to-Agent communication is enabled
                Object[] args = getArguments();
                if (args.length > 0) {
                    CondVar latch = (CondVar) args[0];
                    latch.signal();
                }
    
                // Add a suitable cyclic behaviour...
                addBehaviour(new CyclicBehaviour() {
    
                    public void action() {
                        // Retrieve the first object in the queue and print it on
                        // the standard output
                        Object obj = getO2AObject();
                        if (obj != null) {
                            System.out.println("Got an object from the queue: [" + obj + "]");
                        } else
                            block();
                    }
    
                });
            }
    
            public void takeDown() {
                // Disables the object-to-Agent communication channel, thus
                // waking up all waiting threads
                setEnabledO2ACommunication(false, 0);
            }
    
        } // End of CustomAgent class
    
        public static void main(String args[]) {
    
            try {
                Runtime rt = Runtime.instance();// 获取jade运行时
    
                // Exit the JVM when there are no more containers around
                rt.setCloseVM(true);
    
                // 看运行参数中是否有-container
                if (args.length > 0) {
                    if (args[0].equalsIgnoreCase("-container")) {
                        // 创建一个默认的profile
                        Profile p = new ProfileImpl(false);
                        // p.setParameter(Profile.MAIN, "false");
    
                        // Create a new non-main container, connecting to the default
                        // main container (i.e. on this host, port 1099)
                        System.out.println("Launching the Agent container ..." + p);
                        AgentContainer ac = rt.createAgentContainer(p);
    
                        // 创建一个新的Agent
                        AgentController dummy = ac.createNewAgent("inProcess",
                                "jade.tools.DummyAgent.DummyAgent", new Object[0]);
    
                        // 启动它
                        System.out.println("Starting up a DummyAgent...");
                        dummy.start();
    
                        // 等10秒
                        Thread.sleep(10000);
    
                        // 杀死这个Agent
                        System.out.println("Killing DummyAgent...");
                        dummy.kill();
    
                        // 在同一虚拟机上创建另一个容器,NB,
                        // NB. 两个容器不能共享同一个 Profile对象!!! -->
                        // 所以需再创建一个profile对象
                        p = new ProfileImpl(false);
                        // p.putProperty(Profile.MAIN, "false");
                        AgentContainer another = rt.createAgentContainer(p);
    
                        // 用两个参数创建一个移动agnet
                        Object[] arguments = new Object[2];
                        arguments[0] = "Hello World!";
                        arguments[1] = dummy;
                        AgentController mobile = another.createNewAgent("Johnny",
                                "examples.mobile.MobileAgent", arguments);
                        mobile.start();
    
                        return;
                    }
                }
    
                // 在8888端口运行一个完整的平台t
                // create a default Profile
                Profile pMain = new ProfileImpl(null, 8888, null);
    
                System.out.println("Launching a whole in-process platform..." + pMain);
                AgentContainer mc = rt.createMainContainer(pMain);
    
                // 使用默认的profile启动一个容器
                ProfileImpl pContainer = new ProfileImpl(null, 8888, null);
                System.out.println("Launching the Agent container ..." + pContainer);
                AgentContainer cont = rt.createAgentContainer(pContainer);
                System.out.println("Launching the Agent container after ..." + pContainer);
    
                System.out.println("Launching the rma Agent on the main container ...");
                AgentController rma = mc.createNewAgent("rma", "jade.tools.rma.rma", new Object[0]);
                rma.start();
    
                // Launch a custom Agent, taking an object via the
                // object-to-Agent communication channel. Notice how an Object
                // is passed to the Agent, to achieve a startup synchronization:
                // this Object is used as a POSIX 'condvar' or a Win32
                // 'EventSemaphore' object...
    
                CondVar startUpLatch = new CondVar();
    
                AgentController custom = mc.createNewAgent("customAgent", CustomAgent.class.getName(),
                        new Object[] { startUpLatch });
                custom.start();
    
                // Wait until the Agent starts up and notifies the Object
                try {
                    startUpLatch.waitOn();
                } catch (InterruptedException ie) {
                    ie.printStackTrace();
                }
    
                // Put an object in the queue, asynchronously
                System.out.println("Inserting an object, asynchronously...");
                custom.putO2AObject("Message 1", AgentController.ASYNC);
                System.out.println("Inserted.");
    
                // Put an object in the queue, synchronously
                System.out.println("Inserting an object, synchronously...");
                custom.putO2AObject(mc, AgentController.SYNC);
                System.out.println("Inserted.");
    
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    
    }

    现在看看servlet能不能调用这个,在Eclipse中建立一个web工程,添加jade库,建立一个servlet在servlet中进行调用Agent,看能不能输出结果。
    其中主要文件如下
    文件名:StartServlet.java:

    package examples;
    
    /** 
     * @function 
     * @author Jacksile E-mail:tufujietec@foxmail.com 
     * @date 2016年1月15日 下午12:57:37 
     */
    
    import jade.core.Profile;
    import jade.core.ProfileImpl;
    import jade.core.Runtime;
    import jade.wrapper.AgentContainer;
    import jade.wrapper.AgentController;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class StartServlet extends HttpServlet {
    
        protected void processRequest(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            response.setContentType("text/html;charset=UTF-8");
            PrintWriter out = response.getWriter();
    
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Servlet StartServlet</title>");
            out.println("</head>");
            out.println("<body>");
            out.println("<h1>Servlet StartServlet at " + request.getContextPath() + "</h1>");
            out.println("<font size=10 >你好</font>");
            try {
                Runtime rt = Runtime.instance();
                rt.setCloseVM(true);
                Profile pMain = new ProfileImpl(null, 8888, null);
    
                AgentContainer mc = rt.createMainContainer(pMain);
                // set now the default Profile to start a container
                ProfileImpl pContainer = new ProfileImpl(null, 8888, null);
                out.println("运行Agent容器 ..." + pContainer);
                AgentController rma = mc.createNewAgent("rma", "jade.tools.rma.rma", null);
                rma.start();
                AgentController custom = mc.createNewAgent("custom", "examples.CustomAgent", null);
                custom.start();
    
                out.println("我已经启动了一个小Agent");
    
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            out.println("</body>");
            out.println("</html>");
    
            out.close();
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            processRequest(request, response);
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            processRequest(request, response);
        }
    
        public String getServletInfo() {
            return "Short description";
        }
    }

    CustomAgent.java:

    package examples;
    
    /** 
     * @function 
     * @author Jacksile E-mail:tufujietec@foxmail.com 
     * @date 2016年1月15日 下午1:03:40 
     */
    import jade.core.Agent;
    import jade.core.behaviours.SimpleBehaviour;
    
    public class CustomAgent extends Agent {
    
        public void setup() {
            SimpleBehaviour helloBehaviour = new SimpleBehaviour(this) {
                boolean finished = false;
    
                public void action() {
                    System.out.println("Hello World Behaviour run: 你好,世界!");
                    System.out.println("-----我是:-----");
                    System.out.println("我的本地名称是:" + getLocalName());
                    System.out.println("我全局唯一的标志名称为:" + getName());
                    finished = true;
                    try {
                        Thread.sleep(40000);
                    } catch (java.lang.InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("已经过了40秒钟");
                    // 这里是为了测试关掉IE之后控制台上还会不会输出信息。
                }
    
                public boolean done() {
                    return finished;
                }
    
            };
            addBehaviour(helloBehaviour);
        }
    
    }

    web.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
      <display-name>jade</display-name>
       <servlet>
            <servlet-name>StartServlet</servlet-name>
            <servlet-class>examples.StartServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>StartServlet</servlet-name>
            <url-pattern>/StartServlet</url-pattern>
        </servlet-mapping>
        <session-config>
            <session-timeout>
                30
            </session-timeout>
        </session-config>
      <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
      </welcome-file-list>
    </web-app>

    在url:http://localhost:8888/jade/StartServlet中看到如下结果:
    Servlet StartServlet at /jade
    你好 运行Agent容器 ...(Profile main=true local-host=59.73.87.114 port=8888 services=jade.core.mobility.AgentMobilityService;jade.core.event.NotificationService host=59.73.87.114 local-port=8888 mtps=[jade.mtp.http.MessageTransportProtocol] jvm=j2se) 我已经启动了一个小Agent
    在Tomcat控制台上输出信息:
    Hello World Behaviour run: 你好,世界!
    -----我是:-----
    我的本地名称是:custom
    我全局唯一的标志名称为:custom@deepin-84e2a07b:8888/JADE
    已经过了40秒钟
    同时图形化JADE容器运行,其中“已经过了40秒钟”是在浏览器关闭之后显示,说明Agent容器及Agent启动后一直运行着。
    奇怪的是,我每次退出主容器,总显示
    Exception while removing reference: java.lang.InterruptedException
    java.lang.InterruptedException
            at java.lang.Object.wait(Native Method)
            at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:116)
            at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:132)
            at sun.java2d.Disposer.run(Disposer.java:107)
            at java.lang.Thread.run(Thread.java:595)
    AWT blocker activation interrupted: //后面这个是JADE GUI的bug么?
    java.lang.InterruptedException
            at java.lang.Object.wait(Native Method)
            at java.lang.Object.wait(Object.java:474)
            at sun.awt.AWTAutoShutdown.activateBlockerThread(AWTAutoShutdown.java:309)
            at sun.awt.AWTAutoShutdown.setToolkitBusy(AWTAutoShutdown.java:226)
            at sun.awt.AWTAutoShutdown.notifyToolkitThreadBusy(AWTAutoShutdown.java:118)
            at sun.awt.windows.WToolkit.eventLoop(Native Method)
            at sun.awt.windows.WToolkit.run(WToolkit.java:269)
            at java.lang.Thread.run(Thread.java:595)
    不知道什么问题?
    一个Agent如何以程序的方式生成另一个Agent:
    可以通过以下方式进行创建:

    String name = "Alice" ;
            AgentContainer c = getContainerController();
            try {
                AgentController a = c.createNewAgent( name, "Pong", null );
                a.start();
            }
            catch (Exception e){}

    其中,createNewAgent方法的第一个参数是要创建的Agent的名称,第二个是Agent的类名,实际使用时要包括他所在的命名空间(包名),第三个参数是要传入的参数的名称。
    例子:

    package jadePrime.acl;
    
    /** 
     * @function 
     * @author Jacksile E-mail:tufujietec@foxmail.com 
     * @date 2016年1月15日 下午1:08:17 
     */
    /**
     * Program which creates another Agent and sends 
     ------------     it some messages
     comm2.java
     * 
     */
    
    import jade.core.AID;
    import jade.core.Agent;
    import jade.core.behaviours.SimpleBehaviour;
    import jade.lang.acl.ACLMessage;
    import jade.wrapper.AgentContainer;
    import jade.wrapper.AgentController;
    
    public class Comm2 extends Agent {
        String name = "Alice";
        AID alice = new AID(name, AID.ISLOCALNAME);
    
        protected void setup() {
    
            AgentContainer c = getContainerController();
            System.out.println("find container!");
    
            try {
                AgentController a = c.createNewAgent(name, "jadePrime.acl.Pong", null);
                a.start();
                System.out.println("++++pong has created:" + alice);
    
            } catch (Exception e) {
                System.out.println("Create Agent Error!");
                addBehaviour(new SimpleBehaviour(this) {
                    int n = 0;
    
                    public void action() {
                        ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
                        msg.setContent("Message #" + n);
                        msg.addReceiver(alice);
                        System.out.println("+++ Sending: " + n);
                        send(msg);
                        block(1000);
                    }
    
                    public boolean done() {
                        return ++n > 3;
                    }
                });
            }
    
        }
    }

    当我们创建一个Comm2的Agent时,在控制台上会打印出创建alice成功的消息。
    如何收集当前AMS中Agent列表

    package jadePrime.manage;
    
    /** 
     * @function 
     * @author Jacksile E-mail:tufujietec@foxmail.com 
     * @date 2016年1月15日 下午1:09:53 
     */
    
    import jade.core.AID;
    import jade.core.Agent;
    import jade.domain.AMSService;
    import jade.domain.FIPAAgentManagement.AMSAgentDescription;
    import jade.domain.FIPAAgentManagement.SearchConstraints;
    
    public class AMSDump extends Agent {
        protected void setup() {
            AMSAgentDescription[] Agents = null;
            try {
                SearchConstraints c = new SearchConstraints();
                c.setMaxResults(new Long(-1));
                Agents = AMSService.search(this, new AMSAgentDescription(), c);
            } catch (Exception e) {
                System.out.println("Problem searching AMS: " + e);
                e.printStackTrace();
            }
    
            AID myID = getAID();
            for (int i = 0; i < Agents.length; i++) {
                AID AgentID = Agents[i].getName();
                System.out.println((AgentID.equals(myID) ? "*** " : "    ") + i + ": "
                        + AgentID.getName());
            }
            doDelete();
            // System.exit(0);
        }
    
    }// end class AMSDump

    详见:http://www.iro.umontreal.ca/%7Evaucher/Agents/JADE/primer4.html#5

    wps3BA8.tmp

    JADE中如何使用DF(Directory Facilitator)Agent提供的黄页服务。
    这个比较好理解,DF相当于一个目录服务器,每个提供服务的Agent可以向DF注册其服务,然后,其他的Agent可以从DF中查询该类服务,也可以订阅这类服务,如果是后者,那么一旦这类服务被注册到DF中,则订阅方就可以收到。例程如下:
    文件一, DFRegisterAgent.java 服务提供方

    package yellowpages;
    
    /** 
     * @function 
     * @author Jacksile E-mail:tufujietec@foxmail.com 
     * @date 2016年1月15日 下午1:11:14 
     */
    
    import jade.core.Agent;
    import jade.domain.DFService;
    import jade.domain.FIPAException;
    import jade.domain.FIPANames;
    import jade.domain.FIPAAgentManagement.DFAgentDescription;
    import jade.domain.FIPAAgentManagement.Property;
    import jade.domain.FIPAAgentManagement.ServiceDescription;
    
    public class DFRegisterAgent extends Agent {
    
        protected void setup() {
            String serviceName = "unknown";
    
            // 从命令行的参数中读取服务的名称,默认为unknown
            Object[] args = getArguments();
            if (args != null && args.length > 0) {
                serviceName = (String) args[0];
            }
    
            // 注册服务
            System.out.println("Agent " + getLocalName() + " registering service "" + serviceName
                    + "" of type "weather-forecast"");
            try {
                // 必要的几个步骤
                DFAgentDescription dfd = new DFAgentDescription();
                dfd.setName(getAID());
                ServiceDescription sd = new ServiceDescription();
                sd.setName(serviceName);
                sd.setType("weather-forecast");// 设置服务类型为天气预报
                sd.addOntologies("weather-forecast-ontology");
                sd.addLanguages(FIPANames.ContentLanguage.FIPA_SL);
                // 使用服务的一方必须遵循的规范,和具有的本体知识
                sd.addProperties(new Property("country", "Italy"));
                dfd.addServices(sd);
    
                DFService.register(this, dfd);
            } catch (FIPAException fe) {
                fe.printStackTrace();
            }
        }
    }

    文件二.
    DFSubscribeAgent.java订阅方

    package yellowpages;
    
    /** 
     * @function 
     * @author Jacksile E-mail:tufujietec@foxmail.com 
     * @date 2016年1月15日 下午1:12:26 
     */
    import jade.core.AID;
    import jade.core.Agent;
    import jade.domain.DFService;
    import jade.domain.FIPAException;
    import jade.domain.FIPAAgentManagement.DFAgentDescription;
    import jade.domain.FIPAAgentManagement.Property;
    import jade.domain.FIPAAgentManagement.SearchConstraints;
    import jade.domain.FIPAAgentManagement.ServiceDescription;
    import jade.lang.acl.ACLMessage;
    import jade.proto.SubscriptionInitiator;
    import jade.util.leap.Iterator;
    
    public class DFSubscribeAgent extends Agent {
    
        protected void setup() {
            // Build the description used as template for the subscription
            DFAgentDescription template = new DFAgentDescription();
            ServiceDescription templateSd = new ServiceDescription();
            templateSd.setType("weather-forecast");
            templateSd.addProperties(new Property("country", "Italy"));
            template.addServices(templateSd);
    
            SearchConstraints sc = new SearchConstraints();
            // 最多能接受10个结果
            sc.setMaxResults(new Long(10));
    
            addBehaviour(new SubscriptionInitiator(this, DFService.createSubscriptionMessage(this,
                    getDefaultDF(), template, sc)) {
                protected void handleInform(ACLMessage inform) {
                    System.out.println("Agent " + getLocalName() + ": Notification received from DF");
                    try {
                        DFAgentDescription[] results = DFService
                                .decodeNotification(inform.getContent());
                        if (results.length > 0) {
                            for (int i = 0; i < results.length; ++i) {
                                DFAgentDescription dfd = results[i];
                                AID provider = dfd.getName();
                                // 同一个Agent可能提供很多服务,我们只对天气预报感兴趣
                                Iterator it = dfd.getAllServices();
                                while (it.hasNext()) {
                                    ServiceDescription sd = (ServiceDescription) it.next();
                                    if (sd.getType().equals("weather-forecast")) {
                                        System.out.println("Weather-forecast service for Italy found:");
                                        System.out.println("- Service "" + sd.getName()
                                                + "" provided by Agent " + provider.getName());
                                    }
                                }
                            }
                        }
                        System.out.println();
                    } catch (FIPAException fe) {
                        fe.printStackTrace();
                    }
                }
            });
        }
    }

    这样,编译后,我们为了体现发布服务和订阅服务时间上的一致关系,我们从命令行来运行这些类。假设已编译成功,文件标志在某目录下yellowpages DFSubscribeAgent.class 和yellowpages DFRegisterAgent.class,我们在yellowpages目录下运行命令
    java jade.Boot –gui service1: yellowpages.DFRegisterAgent
    系统运行主容器,同时控制台上显示Agent service1 registering service “noname” of type "weather-forecast"
    然后我们在图形界面下,start new Agent,AgentName:subscriber ClassName:yellowpages.DFSubscribeAgent 添加后,控制台上会显示相关启动后的信息,但不会显示收到服务的消息。然后再start new Agent,AgentName:service2 ClassName:yellowpages.DFRegisterAgent 参数设为:rainny,这是控制台上显示注册服务成功的消息和订阅到服务的消息。显示如下:

    wps5752.tmp

    JADE中使用本体:
        Agent之间进行通信要有相同的语言,词汇和协议。在JADE中,Agents之间通信的方式可以有三种:1.使用字符串表达信息的内容,是最基本的方式.当消息内容是原子数据时,这种方式非常便利.2.消息内容使用序列化的java对象,对本地应用,特别是所有Agent都用java实现的情况下也是很有用的.3.为了jade能够以FIPA格式队消息进行编码和解码,扩展预先定义好的类,亦即使用本体的方式。这种方式允许jade的Agent可以同其他异质Agent系统进行互操作。这三种方式下对应设置和获取内容的方法对应如下:
    image
    现在有一些已经存在的language来描述ontologies,如DAML+OIL和OWL,JADE并不直接支持这些ontologies,而是将ontologies编码为java类(比如protégé可以将本体直接导出为java类)。
    本体提供了Agent交互的语义支持,但必须与内容语言结合使用,后者是Agent交互的语法支持。JADE支持的三种内容语言包括:FIPA-SL类似lisp的语言族;Leap-encoding应用于嵌入式开发;JavaCodec,JADE特定的内容语言。

  • 相关阅读:
    BaseServlet的编写
    两个线程交替打印1-100
    java集合中的HashMap源码分析
    mybatis一级缓存与二级缓存的原理
    mybatis的执行流程
    spring IOC的理解
    一文彻底搞懂面试中常问的各种“锁”
    Dubbo相关的基础
    Servlet基础
    文件传输基础
  • 原文地址:https://www.cnblogs.com/tufujie/p/5135650.html
Copyright © 2020-2023  润新知