Why doesn't more Java code use PipedInputStream / PipedOutputStream?
From the Javadocs:
Typically, data is read from a PipedInputStream object by one thread and data is written to the corresponding PipedOutputStream by some other thread. Attempting to use both objects from a single thread is not recommended, as it may deadlock the thread.
This may partially explain why it is not more commonly used.
I'd assume another reason is that many developers do not understand its purpose / benefit.
I too only discovered the PipedInputStream/PipedOutputStream classes recently.
I am developing an Eclipse plug-in that needs to execute commands on a remote server via SSH. I am using JSch and the Channel API reads from an input stream and writes to an output stream. But I need to feed commands through the input stream and read the responses from an output stream. Thats where PipedInput/OutputStream comes in.
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import com.jcraft.jsch.Channel;
Channel channel;
PipedInputStream channelInputStream = new PipedInputStream();
PipedOutputStream channelOutputStream = new PipedOutputStream();
channel.setInputStream(new PipedInputStream(this.channelOutputStream));
channel.setOutputStream(new PipedOutputStream(this.channelInputStream));
channel.connect();
// Write to channelInputStream
// Read from channelInputStream
channel.disconnect();
In your example you're creating two threads to do the work that could be done by one. And introducing I/O delays into the mix.
Do you have a better example? Or did I just answer your question.
To pull some of the comments (at least my view of them) into the main response:
- Concurrency introduces complexity into an application. Instead of dealing with a single linear flow of data, you now have to be concerned about sequencing of independent data flows. In some cases, the added complexity may be justified, particularly if you can leverage multiple cores/CPUs to do CPU-intensive work.
- If you are in a situation where you can benefit from concurrent operations, there's usually a better way to coordinate the flow of data between threads. For example, passing objects between threads using a concurrent queue, rather than wrapping the piped streams in object streams.
- Where a piped stream may be a good solution is when you have multiple threads performing text processing, a la a Unix pipeline (eg: grep | sort).
In the specific example, the piped stream allows use of an existing RequestEntity implementation class provided by HttpClient. I believe that a better solution is to create a new implementation class, as below, because the example is ultimately a sequential operation that cannot benefit from the complexity and overhead of a concurrent implementation. While I show the RequestEntity as an anonymous class, reusability would indicate that it should be a first-class class.
post.setRequestEntity(new RequestEntity()
{
public long getContentLength()
{
return 0-1;
}
public String getContentType()
{
return "text/xml";
}
public boolean isRepeatable()
{
return false;
}
public void writeRequest(OutputStream out) throws IOException
{
output.setByteStream(out);
serializer.write(doc, output);
}
});