平成16年 秋期 基本情報技術者 午後 問12(Java)

Print Friendly, PDF & Email

ここでは、当社の新人研修受講者に向けて、基本情報のJavaの過去問を掲載しています。

想定しているのは、NetBeansなどのIDEにコピー・ペーストしたうえで、自分の正しいと思う答えを埋めて動作を確認するという使い方です。


次の Java プログラムの説明及びプログラムを読んで,設問に答えよ。

〔プログラムの説明〕

プログラムは,A 社のコールセンタのシミュレータである。 A 社はこのシミュレータを,利用者がコールセンタに電話をかけてからオペレータとつながるまでの 待ち時間の推定に利用する。 コールセンタへの一つの電話呼出しに対しては,1人のオペレータだけが応答することができる。

このシミュレータでは,空きオペレータがいる限りは利用者を待たせることはないとする。 例えば,オペレータが2人いるとき,コールセンタに利用者からの電話が60 秒間隔で6回かかってきて,それぞれの通話時間が,130 秒,100 秒,150 秒, 90 秒,110 秒,140 秒だったとすると,利用者の待ち時間は3番目が 10 秒,5番目が30 秒になり,その他は 0 秒である(図1参照)。

なお,このシミュレータでは,実世界の1秒を 0.1 秒でシミュレートする。

図1

プログラムは次のクラスから構成される。

(1) CallCenter

コールセンタを表すクラスである。 コンストラクタの引数にオペレータ数,通話時間の配列,呼出しを発生させる間隔を指定して, シミュレーションを実行する。 次のメソッドと内部クラスをもつ。

 public static void main(String[] args)

シミュレータをテスト用に起動するメソッドである。

 Call answer()

オペレータが,利用者からの呼出しに応答するために呼ぶメソッドである。 オペレータに割り当てる呼出し( Call オブジェクト)を返す。 このメソッドは,オペレータに割り当てるべき呼出しが発生するまで,オペレータのスレッドを待たせる。 ただし,このクラスが生成するすべての呼出しの割当てが完了し, 割り当てるべき呼出しがなくなったときは,null を返す。

 Operator

オペレータをシミュレートするスレッドクラスである。 各オペレータの処理は個別のスレッドで実行される。 コールセンタにかかってきた電話に応答し,通話する。 CallCenter が生成するすべての呼出しの割当てが完了するまで,処理を繰り返す。

(2) Call

利用者からの呼出しを表すクラスである。 コンストラクタの引数には通話時間を指定する。 次のメソッドをもつ。

 public void talk()

オペレータが利用者との通話中の状態をシミュレートするメソッドである。 このメソッドは,オペレータに割り当てられた利用者の待ち時間を秒単位(1秒未満は四捨五入)で 表示した後,通話時間として指定された時間だけ,オペレータのスレッドを停止させる。

プログラムが図1の例をシミュレートした場合の実行結果を,図2に示す。

なお,図中の ( s ) は(秒)を表す。

0(s)
0(s)
10(s)
0(s)
30(s)
0(s)

   図2 実行結果

プログラム中の java.util.Vector は可変長配列を表すクラスであり,次のメソッドをもつ。

 public boolean add(Object obj)

 配列の最後尾に要素 obj を追加する。

 public Object remove(int index)

 index で指定された位置の要素を配列から削除し,削除した要素を返す。 先頭の要素の位置は 0 である。 index より後方の要素は前方に詰められる。

 public boolean isEmpty()

 要素がなければ true を,あれば false を返す。

[プログラム1]

import java.util.Vector;//(注)廃止されたコレクションです
public class CallCenter {
   private final Vector waitingList = new Vector();
   private boolean running; // 呼出し生成中は true
   public static void main(String[] args) {
      int op = 2; // オペレータ数
      // 通話時間(秒)
      long[] duration = {130, 100, 150, 90, 110, 140};
      long interval = 60; // 呼出しを発生させる間隔(秒)
      new CallCenter(op, duration, interval);
   }
   public CallCenter(int op, long[] duration, long interval) {
      running = true;
      // オペレータのスレッドを生成し,開始する。
      for (int i = 0; i < op; i++) new Operator().start();
      long nextCallTime = System.currentTimeMillis();
      for (int i = 0; i < duration.length; i++) {
         // 呼出しを一つ生成し,リストに追加する。
         synchronized (waitingList) {
            waitingList.add(new Call(duration[i]));
            waitingList.notify();
         }
         // 次の呼出しを生成するまで待つ。
         nextCallTime += interval * 100;      // 10 倍の速さで動作
         long sleeping = /* a */;
         try {
            if (sleeping > 0) Thread.sleep(sleeping);
         } catch (InterruptedException ie) {}
      }
      // すべてのオペレータのスレッドを終了させる/P>
      running = false;
      /* b */{
         waitingList.notifyAll();
      }
   }
   Call answer() {
      synchronized (waitingList) {
         while (waitingList.isEmpty()/* c */ ) {
            try {
               /* d */;
            } catch (InterruptedException e) {}
         }
         if (waitingList.isEmpty()) return null;
         return (Call)waitingList.remove(0);
      }
   }
   class Operator extends Thread {
      public void run() {
         Call call;
         /* e */ call.talk(); 
      }
   }
}

[プログラム2]

public class Call {
   private final long start, duration;
   public Call(long duration) {
      this.duration = duration;
      start = System.currentTimeMillis();
   }
   public void talk() {
      long elapsed = System.currentTimeMillis() - start;
      // 経過時間を四捨五入して表示する/P>
      System.out.println(/* f */+ "(s)");
      try {
         Thread.sleep(duration * 100);        // 10 倍の速さで動作
      } catch (InterruptedException ie) {}
   }
}

設問1 プログラム中の/*  */ に入れる正しい答えを, 解答群の中から選べ。

a に関する解答群

ア nextCallTime

イ nextCallTime - duration[i] * 100

ウ nextCallTime - System.currentTimeMillis()

エ System.currentTimeMillis() - nextCallTime

b に関する解答群

ア for (int i = 0; i < op; i++)

イ if (waitingList != null)

ウ synchronized (this)

エ synchronized (waitingList)

c に関する解答群

ア && !running        イ && running

ウ == !running        エ || running

d に関する解答群

ア notify()          イ wait()

ウ waitingList.notify()    エ waitingList.wait()

e に関する解答群

ア if ((call = answer()) != null)

イ if (answer() != null)

ウ while ((call = answer()) != null)

エ while (answer() != null)

f に関する解答群

ア (elapsed + 50) / 100    イ (elapsed + 500) / 100

ウ (elapsed - 50) / 100    エ (elapsed - 500) / 100

設問2 CallCenter のインスタンスを,次に示すようにして生成したとき, インスタンスが生成されてからシミュレータの時間で 80 秒後(実時間で8秒後)に 通話中の状態にあるオペレータの人数を,解答群の中から選べ。

new CallCenter(3, new long[]{70, 90, 100, 110}, 30);

解答群

ア 0    イ 1    ウ 2    エ 3