令和元年 秋期 基本情報技術者 午後 問11
問11 Java
次の Java プログラムの説明及びプログラムを読んで,設問1,2に答えよ。 〔プログラムの説明〕 スマートフォンやタブレット端末といった携帯端末に通知メッセージを配信するシステム (以下,通知システムという)を模したプログラムである。この通知システムは, メール着信を通知するメッセージを非同期で携帯端末に配信する。このプログラムでは, 通知メッセージを配信する処理及び各携帯端末の処理を,それぞれ独立したスレッドとして実行する。 このプログラムは,次のインタフェース及びクラスから成る。 ここで,各コンストラクタ及びメソッドには,正しい引数が与えられるものとする。 (1) インタフェース NotificationListener は,通知メッセージを受け取るためのメソッドを定義する。 以下,NotificationListener のインスタンスをリスナという。 A メソッド send は,引数で指定された利用者名で登録されている各携帯端末に, 引数で指定された文字列を通知メッセージとして配信する。 携帯端末に対して未配信の通知メッセージがある場合, 引数のメッセージを未配信のメッセージリストに追加する。 B メソッド loopForMessages は,引数で指定された携帯端末に対して, 通知メッセージがあれば携帯端末のリスナに通知し,なければ通知メッセージを受け取れる状態 (以下,待ち受け状態という)にする。この処理を,通知システムが停止されるまで繰り返す。 C メソッド shutdown は,通知システムを停止する。未配信の全メッセージ, 全利用者名及び全携帯端末名の登録情報を削除し,登録されている全携帯端末の待ち受け状態を解除する。 A メソッド createUserMobileDevice は,利用者名とその携帯端末名を登録して, 通知メッセージを受信できる状態にする処理を,新しく生成したスレッドで実行する。 図1は,クラス Tester のメソッド main を実行して得られた出力の例である。 ここで,プログラムは,スレッドの実行速度及び事象発生に対する応答が十分速いシステムで 実行されるものとする。また,スレッドのスケジューリングによって,各行の出力順は異なることがある。
図1 メソッド main の実行結果の例 〔プログラム1〕 import java.util.List; 〔プログラム2〕 public final class MobileDevice { private final String name; private final NotificationListener listener; public MobileDevice(String name, NotificationListener listener) { this.name = name; this listener = listener; } public NotificationListener getListener() { return listener; } public String getName() { return name; } } 〔プログラム3〕 import java.util.ArrayList, import java.util.HashMap; import java.util.List; import java.util.Map; public final class Notifier { private static final Notifier INSTANCE = new Notifier(); private final Obiect lock = new Object(); // 利用者ごとに携帯端末を管理 private final Map<String, List<MobileDevice>> userMobileDevices = new HashMap<>(); // 携帯端末ごとに通知メッセージを保持 private final Map<MobileDevice, List<String>> messagesToDeliver = new HashMap<>(); private volatile boolean active = true; public static Notifier getInstance() { return a ; } private Notifier() { } public void register(String user, MobileDevice device) { synchronized (lock) { List<MobileDevice> devices = userMobileDevices.get(user); if (devices == null) { devices = new ArrayList<>(); userMobileDevicer.put( b ); } devices.add(device); } } public void send(String user, String message) { List<MobileDevice> devices = new ArrayList<>(); synchronized (lock) { if (userMobileDevices.containsKey(user)) { for (MobileDevice device : userMobileDevices.get(user)) { List<String> messageList = messagesToDeliver.get(device); if (messageList == null) { messageList = new ArrayList<>(); messagesToDeliver.put( c ); } messageList.add(message); devices.add(device); } } } for (MobileDevice device : devices) { synchronized (device) { // 通知メッセージがあることを待ち受け状態のスレッドに通知 device.notifyAll(); } } } public void loopForMessages(MobileDevice device) { while(active) { List<String> messageList; synchronized (lock) { messageList = messagesToDeliver.remove(device); } if (messageList != null) { device.getListener().onNotificationReceived(messageList); } synchronized (device) { try { // 通知メッセージが到着するかタイムアウトするまで待つ device.wait(3ØØØL); } catch (InterruptedException e) { break; } } } } public void shutdown() { active = false; List<MobileDevice> devices = new ArrayList<>(); synchronized (lock) { messagesToDeliver.clear(); for (String user : userMobileDevices.keySet()) { for (MobileDevice device : userMobileDevices.get(user)) { devices.add(device); } } userMobileDevices clear(); } for (MobileDevice device : devices) { synchronized (device) { // 待ち受け状態のスレッドに通知 device.notifyAll(); } } } } 〔プログラム4〕 public class Tester { public static void main(String[]args d InterruptedException { createUserMobileDevice("Taro", "phone"); createUserMobileDevice("Taro", "tablet"); Notifier notifier = Notifier.getInstance(); notifier.send("Taro", "You have a message."); Thread.sleep(5ØØL); notifier.shutdown(); /* α */ } private static void createUserMobileDevice(String user, String name) { MobileDevice device = new MobileDevice(name, messageList -> System.out.println( e + ": " + messageList)); Notifier notifier = Notifier.getInstance(); notifier.register(user, device); new Thread(() -> { notifier.loopForMessages(device); System.out.printf("Terminating %s's %s%n", user, name); }).start(); } }
a に関する解答群 エ Notifier() オ Notifier.class カ this b, c に関する解答群 エ user, device オ user, devices カ user, messageList d に関する解答群 エ throw オ throws カ uses e に関する解答群 エ Tester.this.name オ this.name カ user
図2 /* α */ と置き換える行 解答群 イ “tablet: [You have 2 messages.]”だけを出力する。 ウ メソッド loopFormessages で,NullPointerException が発生する。 エ メソッド send で,NullPointerException が発生する。 オ 利用者名 Taro が登録されていないので,メソッド send は何もしないで終了する。 カ 利用者名 Taro は登録されているが,利用者名 Taro の携帯端末が何も登録されていないので, メソッド send は何もしないで終了する。 [←前の問題] [次の問題→] [問題一覧表] [分野別] [基本情報技術者試験TOP ] | |||||