import java.io.BufferedReader; import java.io.InputStreamReader; import java.rmi.Naming; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; import java.util.Stack; public class ClientImpl extends UnicastRemoteObject implements Client { private Server server; public ClientImpl () throws RemoteException { super (); } public void option1_from_server () throws RemoteException { System.out.println ("In option 1 from server"); } public String option2_from_server () throws RemoteException { System.out.print ("In option 2 from server, enter text: "); return getUserInput (); } public void go () { int id = 0; try { server = (Server) Naming.lookup ("//localhost:4236/Server"); id = server.connect (this); } catch (Exception e1) { e1.printStackTrace(); } /* * Start the main client loop, which allows players to view * the list of other players, get statistics, or start a game. */ try { while (true) { int choice = getMenuChoice (); switch (choice) { case 1: server.option1 (id); break; case 2: { String result = server.option2 (id); System.out.println ("Server returned " + result); break; } case 3: System.exit (0); } } } catch (RemoteException e) { e.printStackTrace(); } } public static void main (String[] args) { try { ClientImpl client = new ClientImpl (); client.go (); } catch (Exception e) { e.printStackTrace (); } } private int getMenuChoice () { int result; do { displayMenu (); try { String line = getUserInput (); System.out.println ("Getting menu choice, input was " + line); result = Integer.parseInt (line); } catch (NumberFormatException e) { System.out.println ("You must enter a number between 1 and 3"); result = 0; } } while (result < 1 || result > 3); return result; } private void displayMenu () { System.out.println ("Input Blocking Example"); System.out.println ("1. Option 1 (no input in server call)"); System.out.println ("2. Option 2 (input in server call)"); System.out.println ("3. Quit"); } /* * Everything from here to the end of the class can be pasted into * your code to help with solving the input blocking problem. */ private static Stack inputStack = new Stack (); private static String getUserInput () { BufferedReader keyboard = new BufferedReader (new InputStreamReader (System.in)); try { /* * This is a bit odd, but necessary because we're using keyboard * input. If two threads are waiting for keyboard input, we need * to fill the last request first, so we use a stack to keep track * of threads waiting for input. * * Note that java.util.Stack is synchronized for us already at * the method level, but we also need to synchronize a bit * ourself. */ inputStack.push(Thread.currentThread()); while (true) { if (keyboard.ready ()) { /* * There's some input waiting, but make sure that * we're the last thread to ask for input. Synchronize * all this so that no other threads can start asking for * input while we're in here. */ synchronized (inputStack) { if (Thread.currentThread().equals(inputStack.peek())) { // We are the last thread, so get the input inputStack.pop(); return keyboard.readLine (); } } } Thread.sleep (500); } } catch (Exception e) { e.printStackTrace (); } return ""; } }