| Duplicate :   | |
| Relates :   | |
| Relates :   | |
| Relates :   | |
| Relates :   | |
| Relates :   | |
| Relates :   | 
Name: mc57594			Date: 01/27/97
below is a program to reproduce the problem-
// This program demonstrates how the PipedInputStream object is not
// thread safe.   
//
// What *should* happen is that the consumer thread should run 
// and print notification when a read() is completed from each of
// the 4 producer threads.  What *does* happen is the consumer reads
// the data from the first producer, then is thrown a Pipe broken
IOException.
// Ignoring the IOException is not a valid option, as the pipe will
// continue to receive exceptions at a rate of about 1/second, instead
// of just blocking.
//
// PipedInputStream 'remembers' the thread ID of the
// writer when the receive() method of the object is called to write
// data into the pipe.  When the read() method is called, and there
// is no data available to be read, PipedInputStream should block.
// Before it will block, it checks to see if the writer thread
// is still alive (presumably to see if there is hope of ever unblocking
// again).  Unfortunately, if there is more than one thread that will
// be writing to the pipe, and the last one that visited the receive()
// method has terminated, the pipe will not block, and it will throw
// a broken pipe IOException instead.
//
// There should be 1) a way to specify several threads that are
'eligible'
// to write to the pipe, 2) a way to selectively disable the isAlive()
check 
// in the read() method altogether, and/or 3) access to the writeSide
member
// to allow the user to focus the isAlive() check on a different thread.
// None of the 'useful' bits of PipedInputStream are public, so the only
// way to subclass it and alter this behavior is to write something that 
// resides in the package java.io, which is not a 'clean' solution.
//
// Pat Mancuso
// Cabletron Systems, Inc.
// ###@###.### 
import java.io.*;
/* 
 * The producer class sleeps a specified time, then writes into the
pipe.
 */
class Producer extends Thread
{
  PipedOutputStream pos = null;
  int wait = 0;
  public Producer(PipedOutputStream p, int w) 
  {
    pos = p;
    wait = w;
  }
  public void run()
  {
    byte b[] = new byte[1];
    b[0]='a';
    try {
      System.out.println("Producer sleeping "+wait+" seconds...");
      sleep(wait*1000);
      System.out.println("...slept "+wait+" seconds, writing");
    } catch (Exception e) {
      System.out.println("Producer sleep interrupted!");
      return;
    }
    try {
      pos.write(b, 0, 1);
    } catch (IOException e) {
      System.out.println("producer caught IOException: "+e.toString());
    }
  }
}
/* 
 * The consumer class should read from the pipe forever
 */
class Consumer extends Thread
{
  PipedInputStream pis;
  public Consumer(PipedInputStream p)
  {
    pis = p;
  }
  public void run()
  {
    int i;
    while (true) {
      try {
        i = pis.read();
        System.out.println("consumer read()");
      } catch (IOException e) {
        System.out.println("consumer caught IOException:
"+e.toString());
        // comment out the 'return' below to retry after each exception.
        // this 'works', but wasteful, as the consumer is constantly
        // receiving exceptions at a rate of about 1/second.
        return;
      }
    }
  }
}
public class PipeTest
{
  static public PipedInputStream pis = null;
  static public PipedOutputStream pos = null;
  public static void main(String argv[]) {
    try {
      pis = new PipedInputStream();
      pos = new PipedOutputStream(pis);
    } catch (IOException e) {
      System.out.println("main() caught IOException: "+e.toString());
    }
    // set up consumer - it will block on the read() since
    // writeSide is null initially.
    Consumer consumer = new Consumer(pis);
    
    // set up several producers to wake up at various times
    Producer producer1 = new Producer(pos, 0);
    Producer producer2 = new Producer(pos, 5);
    Producer producer3 = new Producer(pos, 10);
    Producer producer4 = new Producer(pos, 15);
    // start everything off
    consumer.start();
    producer1.start();
    producer2.start();
    producer3.start();
    producer4.start();
    
  }
  
}
======================================================================
| 
 |