将`BufferedReader`转换为`Stream `并行方式

问题描述 投票:6回答:3

[是否有一种方法可以从Stream<String> stream中接收BufferedReader reader,以使stream中的每个字符串都代表reader的一行,并且附加条件是直接提供stream(在读取reader之前)一切)?我想并行处理stream的数据,以便从reader中获取它们以节省时间。

编辑:我想并行处理读取数据。我不想并行处理不同的行。它们应按顺序处理。

让我们举例说明如何节省时间。假设我们的reader将向我们展示100行。读取一行需要2毫秒,处理一行需要1毫秒。如果我先阅读所有行然后进行处理,则需要300毫秒。我想做的是:读取一行后,我要对其进行处理,然后并行读取下一行。然后,总时间将为201毫秒。

我对BufferedReader.lines()的不满意之处:据我了解,当我要处理这些行时,便开始阅读。假设我已经有reader,但必须先进行预计算才能处理第一行。假设它们花费30毫秒。在上面的示例中,使用reader.lines()的总时间为231毫秒或301毫秒(您能告诉我哪个时间正确吗?)。但是可以在201毫秒内完成工作,因为预计算可以与读取前15行并行进行。

java java-8 bufferedreader java-stream
3个回答
8
投票

2
投票

您在看错地方。您以为一行流将读取

来自文件的行,但这不是它的工作原理。您无法告诉底层系统读取行,因为在读取之前没人知道行是什么。
A BufferedReader具有其名称,因为它是

字符缓冲区。该缓冲区的默认容量为8192。每当请求换行时,都会为该换行序列解析该缓冲区,并将返回该零件。当缓冲区中没有足够的字符来查找当前行时,整个缓冲区将被填充

现在,填充缓冲区可能导致请求从基础InputStream读取字节以填充字符解码器的缓冲区。请求多少字节以及实际读取多少字节取决于字符解码器的缓冲区大小,实际编码映射到一个字符的字节数以及基础InputStream是否具有自己的缓冲区以及有多大是。

实际的昂贵操作是从基础流中读取字节,并且从行读取请求到这些读取操作之间没有微不足道的映射。请求第一行可能会导致从底层文件读取一个16 KiB块,而随后的一百个请求可能会从已填充的缓冲区得到处理,并且根本不会产生I / O。而且,您对Stream API所做的任何操作都无法更改此设置。您唯一要并行化的是在缓冲区中搜索换行符,这太简单了,无法从并行执行中受益。

您可以减小所有参与方的缓冲区大小,以便在处理上一行时大致获得预期的并行读取一行的行,但是,并行执行将永远无法弥补因缓冲区大小较小而导致的性能下降。


2
投票
A BufferedReader具有其名称,因为它是

字符缓冲区。该缓冲区的默认容量为8192。每当请求换行时,都会为该换行序列解析该缓冲区,并将返回该零件。当缓冲区中没有足够的字符来查找当前行时,整个缓冲区将被填充

现在,填充缓冲区可能导致请求从基础InputStream读取字节以填充字符解码器的缓冲区。请求多少字节以及实际读取多少字节取决于字符解码器的缓冲区大小,实际编码映射到一个字符的字节数以及基础InputStream是否具有自己的缓冲区以及有多大是。

实际的昂贵操作是从基础流中读取字节,并且从行读取请求到这些读取操作之间没有微不足道的映射。请求第一行可能会导致从底层文件读取一个16 KiB块,而随后的一百个请求可能会从已填充的缓冲区得到处理,并且根本不会产生I / O。而且,您对Stream API所做的任何操作都无法更改此设置。您唯一要并行化的是在缓冲区中搜索换行符,这太简单了,无法从并行执行中受益。

您可以减小所有参与方的缓冲区大小,以便在处理上一行时大致获得预期的并行读取一行的行,但是,并行执行将永远无法弥补因缓冲区大小较小而导致的性能下降。


0
投票
[请帮助我解决类似问题:

Android Java Read With BufferedReader Parallel And AsyncTask MultiThreading

我需要运行2个并行的AsyncTask,但是仅执行一个:

new GetCompaniesCsvFile().execute("companies.csv");

new GetLinesCsvFile().execute("lines.csv");

您能帮我吗?
© www.soinside.com 2019 - 2024. All rights reserved.