通过多个线程访问文件

Ank*_*ani 15 java concurrency file

我想通过10个线程访问一个大文件(文件大小可能从30 MB到1 GB),然后处理文件中的每一行,并通过10个线程将它们写入另一个文件.如果我只使用一个线程来访问IO,则其他线程被阻止.处理花费一些时间几乎相当于从文件系统中读取一行代码.还有一个约束,输出文件中的数据应与输入文件的数据顺序相同.

我想要你对这个系统的设计有所了解.是否有任何现有的API支持并发访问文件?

写入同一文件也可能导致死锁.

如果我关心时间限制,请建议如何实现这一点.

for*_*two 13

我会从三个线程开始.

  1. 读取数据的读取器线程,将其分成"行"并将它们放入有界阻塞队列(Q1),
  2. 从Q1读取的处理线程进行处理并将它们放入第二个有界阻塞队列(Q2),和
  3. 写入线程,从Q2读取并写入磁盘.

当然,我还要确保输出文件与输入文件在物理上不同的磁盘上.

如果处理速度往往比I/O(监视队列大小)慢,那么您可以开始尝试两个或多个并行"处理器",这些"处理器"在读取和写入数据方面是同步的.


mik*_*ike 11

  • 你应该从文件阅读中抽象出来.创建一个读取文件的类,并将内容分派给不同数量的线程.

该类不应该调度字符串,它应该将它们包装在Line包含元信息的类中,例如行号,因为您要保留原始序列.

  • 您需要一个处理类,它可以对收集的数据进行实际操作.在你的情况下,没有工作要做.该类只存储信息,您可以在某一天扩展它以执行其他操作(例如,反转字符串.附加一些其他字符串,...)

  • 然后,您需要一个合并类,它在处理线程上执行某种多路合并排序,并按顺序收集对 Line 实例的所有引用.

合并类也可以将数据写回文件,但要保持代码清洁......

  • 我建议创建一个输出类,它再次从所有文件处理和东西中提取.

当然,如果你缺少主内存,你需要很多内存.你需要一个基于流的方法种的作品就地保留的内存开销很小.


更新基于流的方法

除了以下情况外,保持不变:

Reader线程泵将数据读入一个Balloon.这个气球有一定数量的Line实例可以容纳(数字越大,消耗的主内存就越多).

加工线程Line从气球中取出,读取器在更加空气时将更多的线条泵入气球.

merger类从上面的处理线程中获取行,并且writer将数据写回文件.

也许你应该FileChannel在I/O线程中使用,因为它更适合读取大文件,并且在处理文件时可能消耗更少的内存(但这只是一个估计的猜测).

  • 如果你投票,请解释.因为我一直在寻找机会来提高我的能力.谢谢. (2认同)

BAR*_*BAR 5

任何类型的IO,无论是磁盘,网络等,通常都是瓶颈.

通过使用多个线程,您正在加剧问题,因为很可能一次只有一个线程可以访问IO资源.

最好使用一个线程来读取,将信息传递给工作线程池,然后直接从那里写入.但是,如果工人写到同一个地方会再次出现瓶颈,因为只有一个人可以拥有锁.通过将数据传递给单个编写器线程轻松修复.

简而言之":

单个读取器线程写入BlockingQueue等,这给它一个自然有序的序列.

然后工作线程线程在队列上等待数据,记录其序列号.

工作线程然后将处理过的数据写入另一个BlockingQueue,这次附加其原始序列号

写入线程可以获取数据并按顺序写入.

这可能会产生最快的实施.