为什么更多的Java代码不使用PipedInputStream /PipedOutputStream?

2022-08-31 15:41:27

我最近发现了这个成语,我想知道我是否错过了什么。我从未见过它被使用过。我使用过的几乎所有Java代码都倾向于将数据误入字符串或缓冲区,而不是像这个例子(例如使用HttpClient和XML API):

    final LSOutput output; // XML stuff initialized elsewhere
    final LSSerializer serializer;
    final Document doc;
    // ...
    PostMethod post; // HttpClient post request
    final PipedOutputStream source = new PipedOutputStream();
    PipedInputStream sink = new PipedInputStream(source);
    // ...
    executor.execute(new Runnable() {
            public void run() {
                output.setByteStream(source);
                serializer.write(doc, output);
                try {
                    source.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }});

    post.setRequestEntity(new InputStreamRequestEntity(sink));
    int status = httpClient.executeMethod(post);

该代码使用 Unix 管道样式技术来防止 XML 数据的多个副本保存在内存中。它使用 HTTP Post 输出流和 DOM Load/Save API 将 XML 文档序列化为 HTTP 请求的内容。据我所知,它以很少的额外代码(只有 , 和 的几行)最大限度地减少了内存的使用。RunnablePipedInputStreamPipedOutputStream

那么,这个成语有什么问题呢?如果这个成语没有错,为什么我没有看到它?

编辑:澄清并替换无处不在的样板缓冲区副本,并且它们还允许您在写出处理的数据的同时处理传入的数据。他们不使用操作系统管道。PipedInputStreamPipedOutputStream


答案 1

来自 Javadocs

通常,数据由一个线程从 PipedInputStream 对象读取,数据由其他线程写入相应的 PipedOutputStream。不建议尝试从单个线程同时使用这两个对象,因为它可能会使线程死锁。

这可以部分解释为什么它不是更常用。

我认为另一个原因是许多开发人员不了解其目的/好处。


答案 2

我最近也只发现了PipedInputStream/PipedOutputStream类。

我正在开发一个 Eclipse 插件,它需要通过 SSH 在远程服务器上执行命令。我正在使用JSch,通道API从输入流读取并写入输出流。但是我需要通过输入流馈送命令,并从输出流中读取响应。这就是 PipedInput/OutputStream 的用武之地。

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();

推荐