Some program designs can benefit not only from having multiple threads, but also from having those threads send data to each other. The mechanism that is used to perform this communication is called a pipe. There are two classes that facilitate this work, the PipedOutputStream, which manages the sending of data, and the PipedInputStream, which manages the reception of data. One thread instantiates a PipedOutputStream and writes to it. The other thread instantiates a PipedInputStream and reads from it. Listing 18.11 shows how this works. Listing 18.11 The TestPipes.java File /* * TestPipes.java * * Created on September 27, 2002, 11:29 AM */ package ch18; import java.io.*; /** * * @author Stephen Potts */ public class TestPipes { /** Creates a new instance of TestPipes */ public TestPipes() { } public static void writeData(OutputStream os) { try { DataOutputStream out = new DataOutputStream( new BufferedOutputStream(os)); int[] numArray = { 1, 10, 2, 9, 3, 7, 4, 6, 5, 100, 200 }; for(int i=0; i<numArray.length; i++) { out.writeInt(numArray[i]); } out.flush(); out.close(); }catch (IOException ioe) { ioe.printStackTrace(); } } public static void readData(InputStream is) { try { DataInputStream in = new DataInputStream( new BufferedInputStream(is)); boolean eof = false; while(!eof) { try { int iValue = in.readInt(); System.out.println("read value = " + iValue); }catch(EOFException eofe) { eof = true; } } System.out.println("End of Data"); }catch (IOException ioe) { ioe.printStackTrace(); } } public static void main(String[] args) { try { final PipedOutputStream pos= new PipedOutputStream(); final PipedInputStream pis= new PipedInputStream(pos); Runnable runOutput = new Runnable() { public void run() { writeData(pos); } }; Thread outThread = new Thread(runOutput, "outThread"); outThread.start(); Runnable runInput = new Runnable() { public void run() { readData(pis); } }; Thread inThread = new Thread(runInput, "inThread"); inThread.start(); }catch (IOException ioe) { ioe.printStackTrace(); } } } We create one static method that writes the data. It has to be static because we are going to call it from inside an inner class. public static void writeData(OutputStream os) We take in an OutputStream object and we add the contents of an array to it. DataOutputStream out = new DataOutputStream( new BufferedOutputStream(os)); int[] numArray = { 1, 10, 2, 9, 3, 7, 4, 6, 5, 100, 200 }; The input method is static also. It takes an InputStream as a parameter. public static void readData(InputStream is) We create a BufferedInputStream and read from it until the stream is empty. DataInputStream in = new DataInputStream( new BufferedInputStream(is)); We simply print the data to the console to show that it worked. System.out.println("read value = " + iValue); In the main() method, we instantiate a PipedOutputStream and a PipedInputStream. Notice that the PipedOutputStream is an input to the PipedInputStream constructor. final PipedOutputStream pos= new PipedOutputStream(); final PipedInputStream pis= new PipedInputStream(pos); Using the same anonymous innerclass technique that we have used earlier in this chapter, we call the writeData() method in its own thread. Runnable runOutput = new Runnable() { public void run() { writeData(pos); } }; Thread outThread = new Thread(runOutput, "outThread"); outThread.start(); We call the readData() method in a thread also. Runnable runInput = new Runnable() { public void run() { readData(pis); } }; Thread inThread = new Thread(runInput, "inThread"); inThread.start(); The output from this program is shown here. read value = 1 read value = 10 read value = 2 read value = 9 read value = 3 read value = 7 read value = 4 read value = 6 read value = 5 read value = 100 read value = 200 End of Data Notice that a PipedInputStream and a PipedOutputStream were passed into the writeData() and readData() methods, respectively. This might seem strange to you because the signatures for these methods call for OutputStream and InputStream objects. This works because OutputStream is the parent of PipedOutputStream and InputStream is the parent of PipedInputStream. By the rules of polymorphism, these upcasts are legal. |