code: protected synchronized void receive(int oneByte) throws IOException {
          if (buffer == null || isClosed) {
              throw new IOException("Pipe is closed");
          }
          if (lastReader != null && !lastReader.isAlive()) {
              throw new IOException("Pipe broken");
          }
  
          /*
           * Set the last thread to be writing on this PipedInputStream. If
           * lastWriter dies while someone is waiting to read an IOException of
           * "Pipe broken" will be thrown in read()
           */
          lastWriter = Thread.currentThread();
          try {
              while (buffer != null && out == in) {
                  if (lastReader != null && !lastReader.isAlive()) {
                      throw new IOException("Pipe broken");
                  }
                  notifyAll();
                  wait(1000);
              }
          } catch (InterruptedException e) {
              IoUtils.throwInterruptedIoException();
          }
          if (buffer == null) {
              throw new IOException("Pipe is closed");
          }
          if (in == -1) {
              in = 0;
          }
          buffer[in++] = (byte) oneByte;
          if (in == buffer.length) {
              in = 0;
          }
  
          // let blocked readers read the newly available data
          notifyAll();
      }
docs: Receives a byte and stores it in this stream's {@code buffer}. This
  method is called by {@link PipedOutputStream#write(int)}. The least
  significant byte of the integer {@code oneByte} is stored at index
  {@code in} in the {@code buffer}.
  <p>
  This method blocks as long as {@code buffer} is full.
  
  @param oneByte
  the byte to store in this pipe.
  @throws InterruptedIOException
  if the {@code buffer} is full and the thread that has called
  this method is interrupted.
  @throws IOException
  if this stream is closed or the thread that has last read
  from this stream is no longer alive.