AgentSpace はモーバイルエージェントシステムを実現するためのランタイムシステムと、エージェント作成のためのクラスフレームワークから構成されます。ここではモーバイルエージェントのプログラミングの基礎概念を概説した後、幾つかの例題を示します。
このモーバイルエージェントシステムでは、モーバイルエージェントのプログラムは、一つまたは複数のJavaのクラスから構成されます。ただし、そのうち一つ以上のクラスはクラス Agentを親クラスとして継承する必要があり、さらにそのうち一つは後述のエージェンランタイムからのコールバック呼び出しをうけるクラスとして指定する必要があります(このクラスをブートクラスと呼びます)。なお、以降ではエージェントを定義するためのクラスをエージェントクラス、そのインスタンスを単にエージェントと呼びます。
以下は SimpleAgent という名前のエージェントクラスの例です。
public class SimpleAgent extends Agent { public SimpleAgent() { /* クラスのコンストラクタ */ } ..... }
エージェントクラス(ブートクラス)に含まれる、変数、メソッド名や種類には特に決まりはありませんが、生成、消滅、移動、到着などの状態変化した際に呼び出されるコールバックメッソドは予め決まっています。それらをエージェントクラスに与えることにより、状態変化に際して、エージェントに適切な動作をさせることができます。また、エージェント自信が、複製、消滅、移動、通信などを実現する際には、対応するAPIを呼び出すことによって実現されます。
注意
エージェントクラスのコンストラクター及びメソッドにおいてスレッドを作成すべきではありません。作成してもエージェントが移動または保存する際にスレッドは破棄されます。
エージェントクラス(ブートクラス)のコンストラクターには引数を入れてはいけません。また、現在のシステムでは構いませんが、コンストラクターの中身も空にしておくことを推奨します。これは将来のSunのJavaBenaとの融合の準備のためです。
Agentクラスはその親クラスとしてFrameクラスをもっています。このため、Appletクラスと同様にグラフィックルーチンを記述することができます。
エージェントが、生成、消滅、移動、到着、保存、復活するときにエージェンランタイムから呼び出されるメソッドであり、次のようなものがあります。これらのメソッドは、エージェントの親クラスであるAgentに規定されています。このため、状態変化に対応した動作が必要なければ与える必要はありません。与えない場合はAgentクラスにある対応したメソッドが代わりに呼び出されます。逆に、作成しているエージェント(ブートクラス)でこれらのメソッドをオーバーライトすればブートクラスにあたえたメソッドが代わりに呼び出されます。
上図はエージェントの状態遷移とコールバックメソッドの関係を示したものです。エージェントは生成直後に初期化コールバックメソッドinit()を呼び出されます。そして、次にエージェント生成時の処理を行うコールバックメソッドcreate()が呼びされます。その後の状態においてエージェントはメッセージを受け取ることができるようになります。また、この状態において移動、永続化、停止の動作も可能になります。
void init() { /* do something */ }
クラスファイルからエージェントのファイルを合成するときに一度だけ呼び出されます。エージェントの初期設定などを行うことができますが、後述のエージェントコンテキストなどは使用できません。
void create() { /* do something */ }
エージェントが生成される際に一度だけ呼び出されます。エージェントの初期設定などを行うプログラムを書くとよいでしょう。また、ウィンドウの表示を含むエージェントでは、create()の中で表示するようにすべきです。
void destroy() { /* do something */ }
エージェントが、消滅する直前に呼び出されます。エージェントの終了時の後処理などをここに書くとよいでしょう。ウィンドウの表示を含むエージェントではウィンドウなどを消す処理をここに加えるべきです。
void dispatch(URL url) { /* do something */ }
エージェントが、他のコンピュータに移動するときに、今いるコンピュータを離れる直前に呼び出されます。引数urlには移動先のURLアドレスが入ります。
void arrive() { /* do something */ }
エージェントが、移動先のコンピュータに到着した直後に呼び出されます。現在は引数がありませんが、将来arrive(url)に変更する予定です。
void suspend() { /* do something */ }
エージェントが永続化される直前に呼び出されます。ランライムはsuspend()を呼び出した後に、エージェントのプログラムコードとコンテキスト(状態)を2次記憶上のファイルにします。suspend()の実行を終えると、つぎにresume()が呼び出されるまでエージェントは動作が休止状態になります。
void resume() { /* do something */ }
永続化されたエージェントの再び動作可能になる際に呼び出されます。なお、休止状態から復活したエージェントは識別子が変わります。
void child(AgentIdentifier aid) { /* do something */ }
エージェントの複製が生成された際に呼び出されるメソッドです。ただし、複製をすることにより、同じエージェントが二つ存在することになりますが、このメソッドはその内の一方で呼び出されます。以降では、このメソッドが呼び出されるエージェントを複製されたエージェントまたは子エージェントと呼びます。そしてもう一方を複製したエージェントまたは親エージェントと呼びます。
void toFront() { /* do something */ }
マルチウィンドウシステムでは、エージェントが作成したウィンドウが他のウィンドウの背後になるこがあります。このメソッドは、エージェントランタイムシステムが、このメソッドをもつエージェントが作成したウィンドウが前面に出ることを要求するものです。ウィンドウを前面に移動する処理をこのメソッドに加えます。現在、このメソッドはサポートしていません。
これらのコールバックメソッド(toFront()は除く)は排他的に呼び出されます。つまり、上記のメソッドのうち一つが実行されると他のメソッドを実行することができません。これは、これらのメソッドはエージェントの終了やデータ待避などの基本的な動作をするからです。また、あるコールバックメソッドから別のコールバックメソッドを呼び出さないようにして下さい。これは将来のバージョンでは、コールバックメソッドは Java Reflection の動的メソッド呼び出しを通じて呼び出されるようになるためです。
現在のエージェントランタイムではエージェントは一度に一つのコールバックメソッドしか呼び出されません。このため、シングルスレッドモデルにもとづくことになりますが、ユーザがスレッドを生成することを制限するものではありません。ただし、スレッドはエージェント移動及び永続化の対象になりません。
エージェントコンテキストクラスはエージェントとランタイムシステムとのインターフェースを提供します。
エージェントは、エージェントコンテキストを通してコンピュータのホストアドレス、他のエージェントの識別子などの実行に必要な情報を得ることができます。 また、エージェント間通信のプリミティブもエージェントコンテキスに用意されます。 エージェントコンテキストはAgentContextのクラスから生成されたインスタンスであり、 以下の APIによってそのインスタンスを得ることができます。
AgentContext getAgentContext();
ただし、エージェントコンテキストはエージェントが移動または保存した際には有効ではなくなり、到着または復活した際に再び作られます。このため、到着または復活したときは、getAgentContext()を通じて再び習得するようにして下さい。
public class Hello extends Agent { .... public void create() { AgentContext ac = getAgentContext(); .... } .... }
エージェントコンテキストを取得するときは、安全のため上のようにメソッド変数に 保持すべきです。次にAgentContextのメソッドを示します。
AgentIdentifier[] getAgents()
これを実行したエージェントが存在するランタイムシステム上のエージェントの識別子のリストを返します。
AgentIdentifier getIdentifier()
これを実行したエージェントの識別子を返します。AgentContext クラスには以下のメソッドが用意されている。
Messenger getMessenger();
メッセンジャーオブジェクトを返します。エージェント間通信をする際に実行します。
Messenger getMessenger(AgentIdentifier aid)
エージェント識別子 aid のメッセンジャーオブジェクトを返します。以下のエージェントは create() メソッドでエージェントコンテキストを取得しています。
エージェントコンテキストはエージェント間通信を実現するための幾つか のAPIをもっています。
送信先のエージェント識別子の有無と、引数の数により幾つか種類があります。
void send(AgentIdentifier aid, String name, Object obj1, Object obj2, Object obj3, Object obj4) void send(AgentIdentifier aid, String name, Object obj1, Object obj2, Object obj3) void send(AgentIdentifier aid, String name, Object obj1, Object obj2) void send(AgentIdentifier aid, String name, Object obj1) void send(AgentIdentifier aid, String name)
送信先のエージェント識別子がないときは自分自身に送信します。
void send(String name, Object obj1, Object obj2, Object obj3, Object obj4) void send(String name, Object obj1, Object obj2, Object obj3) void send(String name, Object obj1, Object obj2) void send(String name, Object obj1) void send(String name)
引数の数により幾つか種類があります。
Object call(AgentIdentifier aid, String name, Object obj1, Object obj2, Object obj3, Object obj4) Object call(AgentIdentifier aid, String name, Object obj1, Object obj2, Object obj3) Object call(AgentIdentifier aid, String name, Object obj1, Object obj2) Object call(AgentIdentifier aid, String name, Object obj1) Object call(AgentIdentifier aid, String name)
引数の数により幾つか種類があります。
Future future(AgentIdentifier aid, String name, Object obj1, Object obj2, Object obj3, Object obj4) Future future(AgentIdentifier aid, String name, Object obj1, Object obj2, Object obj3) Future future(AgentIdentifier aid, String name, Object obj1, Object obj2) Future future(AgentIdentifier aid, String name, Object obj1) Future future(AgentIdentifier aid, String name)
エージェントコンテキストの通信メソッドの詳細は後述します。
import java.io.*; public class Hello extends Agent { public Hello() {}; public void create() { AgentContext ac = getAgentContext(); ac.send("hello", "How are you?"); } public void hello(String message) { System.out.println(message+" I am fine."); } }
これを実行するとHow are you? I am fine.」と画面に表示します。
このモーバイルエージェントシステムでは、エージェントが別のエージェントの変数やメソッドを直接呼び出すことはできないようになっています。これは他のエージェントによる(不正な)呼び出しから守るためです。エージェント間で情報を交換する必要があるときには次の通信用のプリミティブを利用して通信をして下さい。また、これらのプリミティブを通じて通常のメソッド呼び出しと比較して、柔軟で並列性を活かした通信を実現することができます。通信の方式には、同期メソッド呼び出し、非同期メソッド呼び出し、一方向の非同期メッセージ送信の3種類があります。また、エージェントだけでなくエージェントランタイムシステムと通信をすることもできます。
現在のシステムでは、エージェント間通信は2種類の方法が実装されています。一つは、送信側のエージェントがメッセージの転送を代行するオブジェクト(メッセンジャーと呼ぶ)に依頼し、予め作成したメッセージを宛先のエージェントに転送してもらうことによって実現するものです。もう一つは、エージェントコンテキスト用意されたメッソドを利用するものです。前者は通信失敗の発見やリモート通信の実現を前提とした方法であり、高機能な通信を提供しますが、ローカルにあるエージェントと通信をする限りは違いはありません。このため、後者は前者を簡便化したものといえます。
送信をするときは次の二つのインスタンスを作ります。
これは通信を代行するオブジェクトとなり、以下のエージェントコンテキストのメソッドを実行することにより取得します。
Messenger getMessenger(AgentIdentifer aid)
メッセージの宛先には通信相手のエージェント識別子を用います。例えば、エージェントコンテキストが ac 、宛先のエージェントの識別子が aid であるとき、それのメッセンジャーインスタンスは m となります。
Messenger m = ac.getMessenger(aid);
Message クラスのインスタンスとなり、引数に送信するメッセージの名前を与えます。メッセージの名前は文字列型の定数でなければなりません。また、大小文字を区別します。
Message(String name);
メッセージの引数は setArg() により設定します。
void setArg(Object obj);
ここで setArg() の引数が通信メッセージの引数となります。引数は0個以上を設定することができ、さらに型に制限はありません。ただし、 引数にはいるオブジェクトはJava のCore API に含まれるクラスからのインスタンスでなければいけません。
受信側では、メッセージ名と一致するメソッドに対して、setArg() で設定した順番の引数列として渡されます。このため、受信側のエージェントに送信メッセージと同じ名前のメソッドがあり、さらにそれの引数の数とそれらの型がその順番を含めて一致する必要があります。
Message msg = new Message("greeting"); msg.setArg("Hello"); msg.setArg("World");
この例は、greeting という名前のメッセージを生成するもので、その引数は、文字列型定数の "Hello" と "World" となります。なお、メソッド名がない場合や引数が一致しない場合は、ランタイムエラーとなります。現在は受信側で生じたランタイムエラーは送信側に伝わりません。このことは、同期的呼び出しをしたときに、受信エラーをおこすと送信側がデッドロックすることを意味する。今後のバージョンでは非同期メッセージ通信以外は受信側エラーを送信側に伝えるようにする予定です。
次に、メッセンジャークラスのインスタンスの送信メソッドを実行します。送信メソッドには、返値の有無、同期の有無により3種類があります。
void sendMessage(Message msg)
引数に与えたメッセージクラスのインスタンス msg をメッセンジャーに指定した識別子をもつエージェントに送信します。ただし、受信側エージェントが結果を返すまではこのメソッドは終了しません(ブロックされます)。
AgentContext ac = getAgentContext(); Messenger m = ac.getMessenger(aid); Message msg = new Message("greeting"); msg.setArg("Hello"); String str = (String)m.sendMessage(msg);
上の例では、まずエージェントコンテキスト ac から、識別子 aid をもつエージェントのメッセンジャーを取得し、それを m に格納します。そして、メッセージ名を greeting とし、その引数を文字列型定数 "Hello" とし送信します。そして、その結果を String 型の変数 str に代入します。
また、受信側エージェントは以下のメソッドの型は以下のようになっている必要があります。
public String greeting(String s);
その例をあげます。
public String greeting(String s) { return s + " World"; }
上記を呼び出すことにより、str には "Hello World" が入ります。
void sendAsyncMessage(Message msg)
引数に与えたメッセージクラスのインスタンス msg をメッセンジャーに指定した識別子をもつエージェントに送信します。受信側エージェントの状態に関わらずブロックせずに送信することができます。ただし、送信した時点で、受信側エージェント自体及び対応するメソッドが存在しない場合、そして引数の数や型が一致しない場合でもエラーを返すことはありません。また、受信側エージェントの結果を受け取ることはできません。
AgentContext ac = getAgentContext(); Messenger m = ac.getMessenger(aid); Message msg = new Message("greeting"); msg.setArg("Hello"); m.sendAsyncMessage(msg);
上の例では、まずエージェントコンテキスト ac から、識別子 aid をもつエージェントのメッセンジャーを取得し、それを m に格納します。そして、メッセージ名を greeting とし、その引数を文字列型定数 "Hello" とし送信します。また、受信側エージェントは引数の型が以下のようになる greeting メソッドをもっている場合だけメッセージを受け取ることができます。
void greeting(String s);
なお、上記のメソッドの返値は任意となります。その例をあげます。
public void greeting(String s) { System.out.println(s+" World"); }
上記を呼び出すことにより、"Hello World" を画面上に表示します。
Future futureMessage(Message msg)
引数に与えたメッセージクラスのインスタンス msg をメッセンジャーに指定した識別子をもつエージェントに送信します。このとき受信側エージェントの状態に関わらずブロックせずに送信します。結果はフュチャークラス (Future) のインスタンスに格納されます。そして、Future クラスのメソッド getReply() を通じてこのインスタンスを読み出すことにより得ることができます。取り出すときはこのメソッドを明示的にキャストする必要があります。
Object getReply()
ただし、フュチャーインスタンスを読み出した時点で、受信側エージェントが結果を返していないときは返えされるまでブロックされます。なお、送信した時点で受信側エージェント自体及び対応するメソッドが存在しない場合、または引数の数や型が一致しない場合でもエラーを返すことはありません。
AgentContext ac = getAgentContext(); Messenger m = ac.getMessenger(aid); Message msg = new Message("greeting"); msg.setArg("Hello"); Future f = m.futureMessage(msg); /* do something */ String str = (String)f.getReply();
上の例では、まずエージェントコンテキスト ac から、識別子 aid をもつエージェントのメッセンジャーを取得し、それを m に格納します。そして、メッセージ名を greeting とし、その引数を文字列型定数 "Hello" とし送信します。そして、その結果を String 型の変数 str に代入します。
また、受信側エージェントは同期メッソド呼び出しの場合と同様となります。
public String greeting(String s);
その例をあげます。
public String greeting(String s) { return s + " World"; }
上記を呼び出すことにより、str には "Hello World" が入ります。
エージェントに到着したメッセージはすべて到着順でメッセージキューに入れられます。このため、メッセージ送信や呼び出しをしてもすぐにそれの処理が開始されるとは限りません。また、メッセージを送信する前に存在していたエージェントでも、実際にメッセージが到着したときには、移動したり終了したりしている可能性があります。このため、通信失敗を考慮したプログラミング必須となります。
現在のランタイムシステムでは、同じランタイムシステム内のエージェント間の通信しかサポートしていません。このため、異なるコンピュータ上のエージェントには通信ができないことなりますが、別のコンピュータ上のエージェントと通信をしたい場合は、エージェントをそのコンピュータに移動させ、そのコンピュータ内のローカルエージェント間通信として実現できます。なお、リモートエージェントへの通信をサポートしないのは、引数に複雑なオブジェクトをもつ場合、その実行コストが上記のエージェント移動による実現と大差がないためです。このため、今後、値や文字列などの定数インスタンスに限定したリモート通信をサポートする可能性はあります。
通信内容に制限はありませんが、その引数にユーザが定義したクラスからのインスタンスを含めることはできません。これはセキュリティを維持するためです。通信内容はJavaのCore API に含まれるクラスからのインスタンスに限るべきです。
エージェントコンテキストのAPIを利用することにより、メッセンジャーオブジェクトやメッセージをオブジェクトを利用することなくエージェント間通信が実現できます。 これはメッセンジャーオブジェクト及びメッセージオブジェクトを呼び出すものと機能的には違いがありません(内部で両オブジェクトを呼び出している)。
メッセンジャークラスと同様にAPIには、返値の有無、同期の有無により3種類があります。
引数の数により幾つか種類があります。
void send(AgentIdentifier aid, String name, Object obj1, Object obj2, Object obj3, Object obj4)
エージェント識別子aid、メッセージ名name、引数obj1〜obj4
void send(AgentIdentifier aid, String name, Object obj1, Object obj2, Object obj3)
エージェント識別子aid、メッセージ名name、引数obj1〜obj3
void send(AgentIdentifier aid, String name, Object obj1, Object obj2)
エージェント識別子aid、メッセージ名name、引数obj1, obj2
void send(AgentIdentifier aid, String name, Object obj1)
エージェント識別子aid、メッセージ名name、引数obj1
void send(AgentIdentifier aid, String name)
エージェント識別子aid、メッセージ名name
送信先のエージェント識別子がないときは自分自身に送信します。
void send(String name, Object obj1, Object obj2, Object obj3, Object obj4)
メッセージ名name、引数obj1〜obj4
void send(String name, Object obj1, Object obj2, Object obj3)
メッセージ名name、引数obj1〜obj3
void send(String name, Object obj1, Object obj2)
メッセージ名name、引数obj1, obj2
void send(String name, Object obj1)
メッセージ名name、引数obj1
void send(String name)
メッセージ名name
識別子aidをもつエージェントのメソッドで名前がname、引数がobj1...をもつものを呼び出します。メソッドの返値を受け取ることはできませんが、送信側エージェントは受信側エージェントの状態に関わらず処理を継続することができます。
ただし、送信した時点で、受信側エージェント自体及び対応するメソッドが存在しない場合、そして引数の数や型が一致しない場合でもエラーを返すことはありません。また、受信側エージェントの結果を受け取ることはできません。
AgentContext ac = getAgentContext(); ac.send("greeting", "hello");
上の例では、まずエージェントコンテキスト ac を取得し、識別子 aid をもつエージェントに名前が"greeting"で、引数が文字型定数"Hello"となる メッセージを送り、続く処理を行うことができます。
受信側エージェントにおいて呼び出されるメソッドの例をあげます。
public void greeting(String s) { System.out.println(s+" World"); }
上記を呼び出すことにより、"Hello World" を画面上に表示します。
引数の数により幾つか種類があります。
Object call(AgentIdentifier aid, String name, Object obj1, Object obj2, Object obj3, Object obj4)
エージェント識別子aid、メッセージ名name、引数obj1〜obj4
Object call(AgentIdentifier aid, String name, Object obj1, Object obj2, Object obj3)
エージェント識別子aid、メッセージ名name、引数obj1〜obj3
Object call(AgentIdentifier aid, String name, Object obj1, Object obj2)
エージェント識別子aid、メッセージ名name、引数obj, obj2
Object call(AgentIdentifier aid, String name, Object obj1)
エージェント識別子aid、メッセージ名name、引数obj1
Object call(AgentIdentifier aid, String name)
エージェント識別子aid、メッセージ名name
識別子aidをもつエージェントのメソッドで名前がname、引数がobj1...をもつものを呼び出します。返値はメソッドの返値となります。このとき、送信側エージェントは受信側エージェントが結果を返すまでブロックされます。
例を示します。
AgentContext ac = getAgentContext(); String s = ac.call(aid, "greeting, "Hello");
上の例では、まずエージェントコンテキスト ac を取得し、識別子 aid をもつエージェントに名前が"greeting"で、引数が文字型定数"Hello"となる メッセージを送り、受信側のメソッドを呼び出します。結果は String 型の 変数 str に代入されます。
また、受信側エージェントは以下のメソッドの型は以下のようになっている必要があります。
public String greeting(String s);
その例をあげます。
public String greeting(String s) { return s + " World"; }
上記を呼び出すことにより、str には "Hello World" が入ります。
引数の数により幾つか種類があります。
Future future(AgentIdentifier aid, String name, Object obj1, Object obj2, Object obj3, Object obj4)
エージェント識別子aid、メッセージ名name、引数obj1〜obj4
Future future(AgentIdentifier aid, String name, Object obj1, Object obj2, Object obj3)
エージェント識別子aid、メッセージ名name、引数obj1〜obj4
Future future(AgentIdentifier aid, String name, Object obj1, Object obj2)
エージェント識別子aid、メッセージ名name、引数obj1〜obj4
Future future(AgentIdentifier aid, String name, Object obj1)
エージェント識別子aid、メッセージ名name、引数obj1〜obj4
Future future(AgentIdentifier aid, String name)
エージェント識別子aid、メッセージ名name、引数obj1〜obj4
識別子aidをもつエージェントのメソッドで名前がname、引数がobj1...をもつものを呼び出します。このとき受信側エージェントの状態に関わらずブロックせずに送信します。結果はフュチャークラス (Future) のインスタンスに格納されます。
そして、Future クラスのメソッド getReply() を通じてこのインスタンスを読み出すことにより得ることができます。取り出すときはこのメソッドを明示的にキャストする必要があります。
Object getReply()
ただし、フュチャーインスタンスを読み出した時点で、受信側エージェントが結果を返していないときは返えされるまでブロックされます。なお、送信した時点で受信側エージェント自体及び対応するメソッドが存在しない場合、または引数の数や型が一致しない場合でもエラーを返すことはありません。
AgentContext ac = getAgentContext(); Future f = ac.future("greeting", "hello"); /* do something */ String str = (String)f.getReply();
上の例では、識別子 aidをもつエージェントに名前greetingで、 引数が"Hello"のメッセンジャーを送信します。結果はフュチャーオブジェクトに 送られますので、それをgetReply()により読み出し、それをString 型の 変数 str に代入します。
また、受信側エージェントは同期メッソド呼び出しの場合と同様となります。
public String greeting(String s);
その例をあげます。
public String greeting(String s) { return s + " World"; }
上記を呼び出すことにより、str には "Hello World" が入ります。
メッセージの名前や引数は自由に設定できます。しかし、幾つかのメッセージは予定されています。
メッセージ名 |
引数の数 |
引数の型 |
メッセージ返値の型 |
dispatch |
1 |
URL |
void |
move |
1 |
URL |
void |
dispose |
0 |
|
void |
clone |
0 |
|
AgentIdentifier |
copy |
0 |
|
AgentIdentifier |
create |
1 |
String |
AgentIdentifier |
suspend |
0 |
|
void |
suspend |
1 |
String |
void |
go |
1 |
URL |
void |
これらのうち、dispatch と dispose 、 suspend 、clone はすでにその動作が実装されています。ただし、これらはその処理の過程でコールバックメソッドを呼び出します。このため、非同期メッセージまたは非同期呼び出し(フュチャー通信)で送るとよいでしょう。
引数として与えたエージェントを URL url でしめしたコンピュータに移動させます。
AgentContext ac = getAgentContext(); Messenger m = ac.getMessenger(); Message msg = new Message("dispatch"); msg.setArg(url); m.sendAsyncMessage(msg);
エージェントコンテキストのAPIを用いた場合は以下のようになります。
AgentContext ac = getAgentContext(); ac.send("dispatch", url);
ここで url は移動先コンピュータの URL アドレスです。ただし、現在のシステムでは他のエージェントを移動させることはできません。このため、エージェントは自分自身にしかこのメッセージを送ることができません。他のエージェントにこのメッセージを送った場合にはセキュリティー例外を発生します。
エージェントを終了させます。引数はとりません。
AgentContext ac = getAgentContext(); Messenger m = ac.getMessenger(); Message msg = new Message("dispose"); msg.setArg(url); m.sendAsyncMessage(msg);
エージェントコンテキストのAPIを用いた場合は以下のようになります。
AgentContext ac = getAgentContext(); ac.send("dispose", url);
エージェントを永続化、つまり、2次記憶上にファイルとして待避します。このメッセージには引数付きとないものの二種類があります。引数を付ける場合は、これが待避しておく先となるファイル名です。このため引数の型は String 型となります。また、引数を付けなかったときは永続化をするときにランタイムシステムがユーザに問い合わせます。
エージェントの複製をつくります。
なお、返値は複製されたのエージェントの識別子となります。
public void test() { AgentContext ac = getAgentContext(); Messenger m = ac.getMessenger(); Message msg = new Message("clone"); Future f = m.futureMessage(msg); .... } public void child(AgentIdentifier aid) { .... }
エージェントコンテキストのAPIを用いた場合は以下のようになります。
public void test() { AgentContext ac = getAgentContext(); Future f = ac.future("clone"); } public void child(AgentIdentifier aid) { .... }
ただし、生成された(子)エージェントは child() を呼びされます。 aidには生成した(親)エージェントの識別子が入ります。一方、親エージェントは、clone 送信の返値として子エージェントの識別子を返します。