当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《为什么没有更多的Java代码使用PipedInputStream/PipedOutputStream?》经验,为你挑选了3个好方法。

我最近发现了这个成语,我想知道是否有我遗失的东西.我从来没有见过它.我在野外工作的几乎所有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 Document序列化为HTTP请求的内容.至于我可以告诉它最大限度地减少用很少的额外代码使用的内存(只是几行了Runnable,PipedInputStreamPipedOutputStream).

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

编辑:澄清PipedInputStreamPipedOutputStream替换到处显示的样板缓冲区副本,它们还允许您在写出已处理数据的同时处理传入数据.他们不使用OS管道.



1> matt b..:

来自Javadocs:

通常,一个线程从PipedInputStream对象读取数据,并且某些其他线程将数据写入相应的PipedOutputStream.建议不要尝试使用单个线程中的两个对象,因为它可能使线程死锁.

这可能部分解释了为什么它不常用.

我假设另一个原因是许多开发人员不了解其目的/利益.


可悲的是,并发性在不需要的地方被过度使用,并且在需要它的地方使用不足......哎呀!:)
所以也许真正的问题是"为什么没有更多的Java代码使用并发?" ...

2> kdgregory..:

在你的例子中,你创建了两个线程来完成一个可以完成的工作.并将I/O延迟引入混合中.

你有更好的例子吗?或者我只是回答你的问题.


将一些评论(至少我对它们的看法)提取到主要回复中:

并发性将复杂性引入应用程序.您现在必须关注独立数据流的排序,而不是处理单个线性数据流.在某些情况下,增加的复杂性可能是合理的,特别是如果您可以利用多个内核/ CPU来执行CPU密集型工作.

如果您处于可以从并发操作中受益的情况,通常有一种更好的方法来协调线程之间的数据流.例如,使用并发队列在线程之间传递对象,而不是将管道流包装在对象流中.

管道流可能是一个很好的解决方案,当你有多个线程执行文本处理时,就是一个Unix管道(例如:grep | sort).


在特定示例中,管道流允许使用由HttpClient提供的现有RequestEntity实现类.我认为更好的解决方案是创建一个新的实现类,如下所示,因为该示例最终是一个顺序操作,无法从并发实现的复杂性和开销中受益.虽然我将RequestEntity显示为匿名类,但可重用性表明它应该是一流的类.

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


他们没有根据消息来源.

3> Brian Matthe..:

我最近也发现了PipedInputStream/PipedOutputStream类.

我正在开发一个Eclipse插件,需要通过SSH在远程服务器上执行命令.我正在使用JSch和Channel 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();

推荐阅读
sx-March23
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有