在多线程应用程序中如何将大文件分割?

5

我在一次面试中被问到了这个基础问题,但我无法回答:

如果我们正在运行一个多线程应用程序,输入是一个大文件,我们必须将其分割成多个部分以便每个线程都可以处理它,那么我们该如何在Java中实现呢?

有没有人能解释一下我们该如何做?任何示例也将不胜感激。


你看过这个答案吗:http://stackoverflow.com/questions/17927398/how-to-split-a-large-text-file-into-smaller-chunks-using-java-multithread - Rookie007
1
请将其制作成链接。 - Skynet
这里存在一个谬论。磁盘,因此文件,不是多线程的。多线程可能会更慢,而不是更快。 - user207421
@EJP 假设磁盘可以处理多线程。 - john
你能使用Java8吗?如果可以,那为什么不考虑使用Streams呢?对于大文件内存映射文件会更好。 - bobs_007
我注意到像Hadoop这样的系统会确保将大文件存储在多台机器上(http://en.wikipedia.org/wiki/Apache_Hadoop#HDFS),这让我觉得解决这个问题的最佳方式可能就是避免它。 - mcdowella
2个回答

1
获取3个起始位置。
    File f = new File("xxx");
    long size = f.length();
    long p1 = 0;
    long p2 = f.length() / 3;
    long p3 = p2 + f.length() / 3;

将位置和长度传递给线程,将文件移动到该位置并读取n个字节。
    FileInputStream is = new FileInputStream("xxx");
    FileChannel c= is.getChannel();
    c.position(position);
    // read ...

long p3 = p2 + f.length() / 3; 这就是它。 - Evgeniy Dorofeev
位置是InputStream将读取下一个字节的起始点。当我们首次打开FileInputStream时,位置为0;当我们读取1个字节时,位置移动到1。FileChannel允许将位置设置为文件内的任何位置。在我们的情况下,我们将线程2的位置设置为文件长度的1/3处,将线程2的位置设置为文件长度的2/3处。 - Evgeniy Dorofeev
1
好的,明白了。当所有线程读取完文件后,我们需要将任何内容与此解决方案合并吗? - john
你应该使用ThreadPoolExecutor,同时提交3个任务,等待3个结果。结果如何处理取决于应用程序逻辑。 - Evgeniy Dorofeev
这取决于操作系统。Java 将尝试并发执行。或者,您可以拥有一个单独的读取器,它读取一块并将其发送到一个线程,然后再读取另一个并发送到另一个线程... - Evgeniy Dorofeev
显示剩余3条评论

1
在面试中,应该回答这是一个消费者-生产者问题。因此,您需要有1个生产者线程读取文件并将行放入同步集合(如Vector),然后您可以有n个消费者线程从集合中获取行并处理它们。
如果需要准备其他面试问题,则可以是:超线程,死锁,繁忙等待。
有一些关于面试的书籍,例如《破解面试代码》或《Java编程面试揭秘》。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接