繁体   English   中英

与独立消费者同时处理单个InputStream

[英]Concurrent processing of single InputStream with independent consumers

我需要生成N个消费者线程,它们同时处理相同的InputStream,例如 - 以某种方式转换它,计算校验和或数字签名等。这些消费者不依赖于彼此,并且所有消费者都使用第三方库,它接受InputStream作为数据来源。

所以我能做的是 - 创建一些InputStream的实现,这将是

  • 从“父”流中读取数据块
  • 解锁消费者
  • 等到每个消费者阅读整个块
  • 读下一个块

虽然看起来很简单,但是当某些消费者死亡时,它可能引发各种问题,例如活锁,实现所有的InputStream方法,使用障碍/锁存器控制消费者自己的叉/连接等。

一位好友告诉我,这是半小时的实施,它是我的晚上。

我更喜欢使用足够成熟的东西(谷歌搜索没有结果因此,我的google-fu还不够好?)或者不打扰并将整个“源”流复制到临时文件中并将其用作数据来源。 后一种解决方案似乎更可靠,但最终可能会创建千兆字节文件(例如处理流式音频时)。

我看待它的方式,你至少应该有某种缓冲,这样不同的消费者可以以不同的速度穿过溪流而不会被当前最慢的消费者所困扰。 这基本上可以确保最坏情况下的性能,并且并发性的好处很少。

比方说,您可以使用目前已使用它的消费者标记每个块,然后删除那些完全用完的块。 也许这可以通过每个消费者持有对尚未使用的每个块的引用来实现,这将允许GC自动处理使用过的块。 生产者可能会将一个WeakReference列表保存到块中,因此它可以处理尚未使用的块数,并以此为基础对其进行限制。

我也在考虑为每个线程提供一个单独的InputStream实例,它在内部与生产者InputStream通信。 通过这种方式,您可以轻松解决您的活锁危险: try ... finally { is.close(); } try ... finally { is.close(); } -垂死的消费者关闭了自己的InputStream。 这是传达给制作人的。

我对每个消费者使用ArrayBlockingQueue有一些想法。 确保所有消费者都得到适当的喂养,而不会让生产者阻止或忙碌等待会有一些困难。

你考虑过使用管道流吗? 您的生产者可以有一个或多个PipedOuputStream ,它会抛出从文件中读取的任何内容。 在管道的另一侧,您可以在相应的PipedInputstream上读取不同的消费者线程(这是一个可以与您的库共享的InputStream)。

您的生产者线程可以决定通过哪个管道数据发送,通过这种方式,为管道另一侧的给定消费者线程读取提供要处理的数据。

如果需要从消费者线程中获取数据,则可以在相反方向创建另一个管道,以将数据发送回给您。

您可以尝试一些Java Messaging Service(JMS)实现,如Apache ActiveMQ

在您的情况下,您需要创建一个所谓的主题 (请参阅主题与队列 )。 主题由生产者创建,并发布给N个消费者,这些消费者可以同时运行,每个消费者接收完全相同的数据。

既然你想使用InputStream那么有一章介绍如何发送消息流

我想,通常情况下,生产者和消费者将是独立的进程,可能在网络上的不同机器上运行。 我认为您可以将其配置为在单个JVM中完全运行。 这取决于JMS的实现。 这些也很有名: JBoss的HornetQRabbitMQ和其他一大堆。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM