Agent Context

タイムアウト付きエージェント間通信

佐藤一郎 1998/9/28

タイムアウト機能付きエージェント間通信API

以下の3つのAPI(send()、call()、future())を利用することにより他のエー ジェントのメソッドを呼び出すことができます。このとき、呼び出される側が そのメソッドを持っているか、そして、それが呼び出し可能であるかを事前に 判定することができます。また、所定時間内に応答がなかった場合はタイムア ウトとして呼び出しをキャンセルすることができます。

なお、タイムアウトとなった際にメソッド呼び出しメッセージが待ち行列中で 処理待ち状態にあるときは待ち行列から外されます。また、すでにメソッドを 呼び出し処理をしているときは、その処理が中断されます。このため処理中の 中断が危険なメソッドはfinalize()などにより中断に備えてください。

エージェントコンテキストのAPI: エージェント間通信メソッド
メソッド名 第一引数の型 メソッド返値の型 例外
send() Message void NoSuchMethodException, NoSuchAgentException
call() Message Object NoSuchMethodException, NoSuchAgentException, TimeoutException, InvocationException
future() Message Future NoSuchMethodException, NoSuchAgentException, TimeoutException, InvocationException

これらのAPIを呼び出す前に、引数のMessageクラスのインスタンスを生成 し、宛先エージェント、引数、タイムアウト時間などを設定します。

メッセージクラスのインスタンス

Message クラスのインスタンスを作るときは、引数に送信するメッセージの名前を与え ます。メッセージの名前は文字列型の定数でなければなりません。また、大小 文字を区別します。

Message(String name);

上記の3つのAPIを利用するときは、通信相手となるエージェントの識別子 をsetTarget()メソッドにより与えます。

void setTarget(AgentIdentifier aid);

メッセージの引数は setArg() により設定します。

void setArg(Object obj);

ここで setArg() の引数が通信メッセージの引数となります。引数は0個以上 の任意個とることができます。型はJava のCore API に含まれるクラスに してください。ユーザが定義したクラスやint型などの基底型は避けるべきです。 受信側では、メッセージ名と一致するメソッドに対して、setArg()で設定した 順番の引数列として渡されます。このため、受信側のエージェントに 送信メッセージと同じ名前のメソッドがあり、さらにそれの引数の数とそれらの 型がその順番を含めて一致する必要があります。

同期呼び出しcall()とフューチャーfuture()ではタイムアウトにより、所定時 間内に通信が完了しなかった場合は通信を中断することができます。

void setTimeout(int timelimit);

引数のtimelimitにはミリ秒単位でデッドライン時間を指定してください。な お、0(ゼロ)の場合はタイムアウトは行わず、通信が終了するまで待つこと になります。

例を示します。これは識別子aidとなるエージェントにメッセージgreetingを 送り、それの第一引数が文字列型の値"Hello"、第二引数が文字列 型の値"World"、そして、タイムアウト時間が1000ミリ秒となるこ とを指定しています。

Message msg = new Message("greeting");

msg.setTarget(aid);

msg.setTimeout(1000);

msg.setArg("Hello");

msg.setArg("World");

次に、メッセンジャークラスのインスタンスの送信メソッドを実行します。送 信メソッドには、返値の有無、同期の有無により3種類があります。

非同期メッセージ送信

一方向の非同期メッセージ送信はsend()により提供されます。

  public Object send(Message msg) throws 

  NoSuchMethodException, NoSuchAgentException

Messageクラスのインスタン スmsgを、それの設定に従って送信します。メソッドの返値を受け取ることは できませんが、送信側エージェントは受信側エージェントの状態に関わらず処 理を継続することができます。msgにはメッセージ名、引数を設定していく必 要があります。

送信した時点で、受信側のエージェントが存在しないときは、例外 NoSuchAgentExceptionとなります。また、受信側エージェントに msgに指定した名前のメソッドが存在しない場合や、引数の数や型が 一致しない場合は例外NoSuchMethodExceptionとなります。なお、 send()では受信側エージェントの結果を受け取ることはできません。 結果が必要なときは後述のcall()future()を使うべきで す。



Message msg = new Message("greeting");

msg.setTarget(aid);

msg.setArg("Hello");

try {

    AgentContext ac = getAgentContext();

    ac.send(msg);

}

catch (NoSuchAgentException e) {

    e.printStackTrace();

}

catch (NoSuchMethodException e) {

    e.printStackTrace();

}

ここでaidは呼び出される側のエージェントの識別子です。 そして、このエージェントは次のようなメソッドを持つべきです。このメソッ ドは公開(public)として宣言され、名前、引数の数と型が上記のmsg と一致しなければいけません。



public void greeting(String s) {

    System.out.println(s+" World");

}

これを実行すると受信側エージェントにより "Hello World" が出力 されます。

同期メソッド呼び出し

他のエージェントメソッドを呼び出し、その結果を得る方法の一つが send()を利用するものです。



public Object call(Message msg) throws 

NoSuchMethodException, NoSuchAgentException

TimeoutException, InvocationException

Messageクラスのインスタン スmsgと指定したメソッドを呼び出します。メソッドの実行結果を call()の返値として受け取ることができます。ただし、メソッドの 実行が終了するまで呼び出し側はブロックされます。

送信した時点で受信側のエージェントが存在しないことがわかると、例外 NoSuchAgentExceptionとなります。また、受信側エージェントに msgに指定した名前のメソッドが存在しないことや、引数の数や型が 一致しないことがわかると例外NoSuchMethodExceptionとなります。 メソッド実行中や実行待ち中に何らかの異常が発生すると InvocationExceptionとなります。

msgに時間制限を設定した場合、call()の実行開始し、そ の時間が経過してもメソッドの実行が終了していない場合はタイムアウトにな り、例外TimeoutExceptionがなげられます。タイムアウトになったとき、 メソッド呼び出し要求が待ち行列中にあるときは待ち行列から外されます。 また、すでにメソッドの実行を開始しているときはその実行が停止されます。



Message msg = new Message("greeting");

msg.setTarget(aid);

msg.setArg("Hello");

msg.setTimeut(1000);

try {

    AgentContext ac = getAgentContext();

    String s = (String)ac.call(msg);

    System.out.println(s);

}

catch (NoSuchAgentException e) {

    e.printStackTrace();

}

catch (NoSuchMethodException e) {

    e.printStackTrace();

}

これは識別子aidをもつエージェントのメソッド greeting(String s)を呼び出すものです。引数には文字列型の値 "Hello"となります。またタイムアウトまでの制限時間を 1000ミリ秒(つまり1秒)と設定しています。また、呼び出される側のこのエー ジェントは次のようなメソッドを持つべきです。このメソッドは公開(public) として宣言され、名前、引数の数と型が上記のmsgと一致しなければ いけません。



public String greeting(String s) {

    String msg = s+" World";

    return msg;

}



Message msg = new Message("greeting");

msg.setTarget(aid);

msg.setArg("Hello");

msg.setTimeut(1000);

try {

    AgentContext ac = getAgentContext();

    String s = (String)ac.call(msg);

    System.out.println(s);

}

catch (NoSuchAgentException e) {

    e.printStackTrace();

}

catch (NoSuchMethodException e) {

    e.printStackTrace();

}

catch (TimeoutException e) {

    e.printStackTrace();

}

catch (InvocationException e) {

    e.printStackTrace();

}

タイムアウトが必要ない場合は以下のように呼び出してください。 なお、タイムアウトの有無に関わらず例外TimeoutExceptionの キャッチをしなければいけません。



Message msg = new Message("greeting");

msg.setTarget(aid);

msg.setArg("Hello");

try {

    AgentContext ac = getAgentContext();

    String s = (String)ac.call(msg);

    System.out.println(s);

}

catch (NoSuchAgentException e) {

    e.printStackTrace();

}

catch (NoSuchMethodException e) {

    e.printStackTrace();

}

catch (TimeoutException e) {

    e.printStackTrace();

}

catch (InvocationException e) {

    e.printStackTrace();

}

結果が必要で、さらに呼び出し側の処理を継続したい場合は future()を利用すべきです。また、結果が必要ない場合は send()を使ってください。

フュチャーメソッド呼び出し

フュチャーメソッド呼び出しとは、フュチャーという仲介オブジェクトをつく り、そのオブジェクトにメソッド呼び出し結果を格納することで、呼び出し側 がメソッド実行を待たずに処理を継続できるようにするものです。また、呼び 出し側がメソッドの実行結果が必要になった場合は、フュチャーオブジェクト から所定のメソッドを通じて取り出します。

なお、呼び出し側がフュチャーオブジェクトからメソッドの実行結果を取り出す 際に、またメソッドの実行が終了していないときはcall()と同様に 呼び出し側はメソッドの実行終了までブロックされます。



public Future future(Message msg) throws 

NoSuchMethodException, NoSuchAgentException

TimeoutException, InvocationException

Messageクラスのインスタン スmsgと指定したメソッドを呼び出します。ただし、送信した時点で 受信側のエージェントが存在しないことがわかると、例外 NoSuchAgentExceptionとなります。また、受信側エージェントに msgに指定した名前のメソッドが存在しないことや、引数の数や型が 一致しないことがわかると例外NoSuchMethodExceptionとなります。 メソッド実行中や実行待ち中に何らかの異常が発生すると InvocationExceptionとなります。

msgに時間制限を設定した場合、future()の実行開始し、そ の時間が経過してもメソッドの実行が終了していない場合はタイムアウトにな り、例外TimeoutExceptionがなげられます。タイムアウトになったとき、 メソッド呼び出し要求が待ち行列中にあるときは待ち行列から外されます。 また、すでにメソッドの実行を開始しているときはその実行が停止されます。

メソッド呼び出しの実行結果はクラスFutureのインスタンスに格 納されます。実行結果はFutureクラスのメソッドgetReply() を通じてこのインスタンスを読み出すことにより得ることができます。 getReply()はクラスObjectを返しますので、必要に応じて メソッドgetReply()を明示的にキャストしてください。



Object getReply()

ただし、メソッドgetReply()により呼び出し結果を読み出した時点 で、メソッド呼び出しが完了していないときは、完了するまでメソッド getReply()は結果を返しませんので、getReply()を実行したエー ジェントはブロックされます。



Message msg = new Message("greeting");

msg.setTarget(aid);

msg.setArg("Hello");

msg.setTimeout(2000);

try {

    AgentContext ac = getAgentContext();

    Future f = ac.future(msg);

    String s = (String)f.getReply();

    System.out.println(s);

}

catch (NoSuchAgentException e) {

    e.printStackTrace();

}

catch (NoSuchMethodException e) {

    e.printStackTrace();

}

catch (TimeoutException e) {

    e.printStackTrace();

}

catch (InvocationException e) {

    e.printStackTrace();

}

これは識別子aidをもつエージェントのメソッド greeting(String s)を呼び出すものです。引数には文字列型の値 "Hello"となります。またタイムアウトまでの制限時間を 2000ミリ秒(つまり2秒)と設定しています。このメソッドは公開(public)と して宣言され、名前、引数の数と型が上記のmsgと一致しなければい けません。結果はクラスFutureのインスタンスfに送られ ますので、それをgetReply()により読み出し、String型にキャストしています。 なお、呼び出される側のこのエージェントは次のようなメソッドを持つべきで す。



public String greeting(String s) {

    String msg = s+" World";

    return msg;

}

 

目次に戻る

Ichiro Satoh (Ph.D.)
Associate Professor,
Deparment of Information Sciences
Ochanomizu University
2-1-1 Ootsuka Bukyo-ku Tokyo 112, JAPAN
Tel: +81-3-5978-5388, Fax: +81-3-5978-5705
Email: ichiro@is.ocha.ac.jp