| ||||
| Copyright 1999 Sams Publishing |
| | ||
| | |
| Using BufferedThreadedInputStream for Interruptible I/O |
| | |
| Now its time to combine the techniques presented so far. CalcServerTwo (see Listing 15.9) has been slightly modified to work with CalcWorkerTwo . CalcWorkerTwo (see Listing 15.10 ) now uses a BufferedThreadedInputStream as an inline filter so that when it is blocked trying to read() , it will respond to an interrupt. |
| | |
| Listing 15.9 CalcServerTwo.javaModified to Work with CalcWorkerTwo |
| | |
| 1: import java.io.*; |
| 2: import java.net.*; |
| 3: import java.util.*; |
| 4: |
| 5: public class CalcServerTwo extends Object { |
| 6: private ServerSocket ss; |
| 7: private List workerList; |
| 8: |
| 9: private Thread internalThread; |
| 10: private volatile boolean noStopRequested; |
| 11: |
| 12: public CalcServerTwo (int port) throws IOException { |
| 13: ss = new ServerSocket(port); |
| 14: workerList = new LinkedList(); |
| 15: |
| 16: noStopRequested = true; |
| 17: Runnable r = new Runnable() { |
| 18: public void run() { |
| 19: try { |
| 20: runWork(); |
| 21: } catch (Exception x) { |
| 22: // in case ANY exception slips through |
| 23: x.printStackTrace(); |
| 24: } |
| 25: } |
| 26: }; |
| 27: |
| 28: internalThread = new Thread(r); |
| 29: internalThread.start(); |
| 30: } |
| 31: |
| 32: private void runWork() { |
| 33: System.out.println( |
| 34: in CalcServer - ready to accept connections); |
| 35: |
| 36: while (noStopRequested) { |
| 37: try { |
| 38: System.out.println( |
| 39: in CalcServer - about to block + |
| 40: waiting for a new connection); |
| 41: Socket sock = ss.accept(); |
| 42: System.out.println( |
| 43: in CalcServer - received new connection); |
| 44: workerList.add(new CalcWorkerTwo (sock)); |
| 45: } catch (IOException iox) { |
| 46: if (noStopRequested) { |
| 47: iox.printStackTrace(); |
| 48: } |
| 49: } |
| 50: } |
| 51: |
| 52: // stop all the workers that were created |
| 53: System.out.println(in CalcServer - putting in a + |
| 54: stop request to all the workers); |
| 55: Iterator iter = workerList.iterator(); |
| 56: while (iter.hasNext()) { |
| 57: CalcWorkerTwo worker = ( CalcWorkerTwo ) iter. next (); |
| 58: worker.stopRequest(); |
| 59: } |
| 60: |
| 61: System.out.println(in CalcServer - leaving runWork()); |
| 62: } |
| 63: |
| 64: public void stopRequest() { |
| 65: System.out.println( |
| 66: in CalcServer - entering stopRequest()); |
| 67: noStopRequested = false; |
| 68: internalThread.interrupt(); |
| 69: |
| 70: if (ss != null) { |
| 71: try { |
| 72: ss.close(); |
| 73: } catch (IOException x) { |
| 74: // ignore |
| 75: } finally { |
| 76: ss = null; |
| 77: } |
| 78: } |
| 79: } |
| 80: |
| 81: public boolean isAlive() { |
| 82: return internalThread.isAlive(); |
| 83: } |
| 84: |
| 85: public static void main(String[] args) { |
| 86: int port = 2001; |
| 87: |
| 88: try { |
| 89: CalcServerTwo server = new CalcServerTwo (port); |
| 90: Thread.sleep(15000); |
| 91: server.stopRequest(); |
| 92: } catch (IOException x) { |
| 93: x.printStackTrace(); |
| 94: } catch (InterruptedException x) { |
| 95: // ignore |
| 96: } |
| 97: } |
| 98: } |
| | |
| Listing 15.10 CalcWorkerTwo.javaUsing BufferedThreadedInputStream |
| | |
| 1: import java.io.*; |
| 2: import java.net.*; |
| 3: |
| 4: public class CalcWorkerTwo extends Object { |
| 5: private DataInputStream dataIn; |
| 6: private DataOutputStream dataOut; |
| 7: |
| 8: private Thread internalThread; |
| 9: private volatile boolean noStopRequested; |
| 10: |
| 11: public CalcWorkerTwo(Socket sock) throws IOException { |
| 12: dataIn = new DataInputStream( |
| 13: new BufferedThreadedInputStream( |
| 14: sock.getInputStream())); |
| 15: dataOut = new DataOutputStream( |
| 16: new BufferedOutputStream( |
| 17: sock.getOutputStream())); |
| 18: |
| 19: noStopRequested = true; |
| 20: Runnable r = new Runnable() { |
| 21: public void run() { |
| 22: try { |
| 23: runWork(); |
| 24: } catch (Exception x) { |
| 25: // in case ANY exception slips through |
| 26: x.printStackTrace(); |
| 27: } |
| 28: } |
| 29: }; |
| 30: |
| 31: internalThread = new Thread(r); |
| 32: internalThread.start(); |
| 33: } |
| 34: |
| 35: private void runWork() { |
| 36: while (noStopRequested) { |
| 37: try { |
| 38: System.out.println(in CalcWorker - about to + |
| 39: block waiting to read a double); |
| 40: double val = dataIn.readDouble(); |
| 41: System.out.println( |
| 42: in CalcWorker - read a double!); |
| 43: dataOut.writeDouble(Math.sqrt(val)); |
| 44: dataOut.flush(); |
| 45: } catch (InterruptedIOException iiox) { |
| 46: System.out.println(in CalcWorker - blocked + |
| 47: read was interrupted !!!); |
| 48: } catch (IOException x) { |
| 49: if (noStopRequested) { |
| 50: x.printStackTrace(); |
| 51: stopRequest(); |
| 52: } |
| 53: } |
| 54: } |
| 55: |
| 56: // In real-world code, be sure to close other streams |
| 57: // and the socket as part of the clean-up. Omitted here |
| 58: // for brevity. |
| 59: |
| 60: System.out.println(in CalcWorker - leaving runWork()); |
| 61: } |
| 62: |
| 63: public void stopRequest() { |
| 64: System.out.println( |
| 65: in CalcWorker - entering stopRequest()); |
| 66: noStopRequested = false; |
| 67: internalThread.interrupt(); |
| 68: System.out.println( |
| 69: in CalcWorker - leaving stopRequest()); |
| 70: } |
| 71: |
| 72: public boolean isAlive() { |
| 73: return internalThread.isAlive(); |
| 74: } |
| 75: } |
| | |
| CalcWorkerTwo has been modified to take advantage of the interruptible I/O of BufferedThreadedInputStream (line 13). The InterruptedIOException has been caught in this code simply to print a message (lines 4547) but can be ignored. The stopRequest() method (lines 6370) has been simplified back down to the self-running object templateonly an interrupt() is necessary to unblock a read() . |
| | |
| The same CalcClient code can be used with the new CalcServerTwo and CalcWorkerTwo . Listing 15.11 shows possible output from CalcServerTwo . Your output should match very closely with only a message or two swapped. |
| | |
| Listing 15.11 Possible Output from CalcServerTwo |
| | |
| 1: in CalcServer - ready to accept connections |
| 2: in CalcServer - about to block waiting for a new connection |
| 3: in CalcServer - received new connection |
| 4: in CalcServer - about to block waiting for a new connection |
| 5: in CalcWorker - about to block waiting to read a double |
| 6: in CalcWorker - read a double! |
| 7: in CalcWorker - about to block waiting to read a double |
| 8: in CalcServer - entering stopRequest() |
| 9: in CalcServer - putting in a stop request to all the workers |
| 10: in CalcWorker - entering stopRequest() |
| 11: in CalcWorker - leaving stopRequest() |
| 12: in CalcWorker - blocked read was interrupted!!! |
| 13: in CalcServer - leaving runWork() |
| 14: in CalcWorker - leaving runWork() |
| | |
| The main difference in the output from what was seen before is line 12. Here, a message is printed confirming that an InterruptedIOException was thrown when the blocked thread was interrupted. |
| | | ||
| Toc | |||