【问题标题】:How can i implement multithreading in java to process 2 million text files?如何在 java 中实现多线程来处理 200 万个文本文件?
【发布时间】:2023-04-01 01:38:01
【问题描述】:

我必须处理大约 200 万个文本文件并在那里生成三元组。

假设我有一个txt文件xyz.txt(200万输入的文件之一),处理如下:

start(xyz.txt)---->module1(xyz.tpd)------>module2(xyz.adv)-------->module3(xyz.tpl)

建议我一个逻辑或概念,以便我可以在 x64 4GB Windows 系统上以优化的方式更快地处理。

module1(working):它使用调用解析器的 .bat 文件解析 txt 文件,它是一个单独的系统线程,15 秒后它再次开始解析另一个 txt 文件,依此类推....

module2(working):它接受.tpd 文件作为输入并生成.adv 文件。 module3(working):它接受.adv 文件作为输入并生成.tpl(triples)。

我应该从 txt 文件还是在其他点启动线程..? 我担心如果我的 CPU 卡在上下文切换中。

谁能有更好的逻辑,让我试试..!?

【问题讨论】:

  • 这 3 个步骤是 CPU 密集型还是您大部分时间都在读取/写入磁盘?
  • 主要是读/写操作,但解析和三重生成是 CPU 密集型的。
  • 如果你有硬盘,你的 200 万个文件大约需要 11 个小时才能访问(但是你必须打开和关闭的文件数量)如果你每 15 秒做一个,这将需要347 天处理。
  • 哇!你提出了一些惊人的事实......所以我现在正在考虑将工作分配给 4 台机器......

标签: java multithreading performance


【解决方案1】:

使用ThreadPoolExecutor 。调整它的参数,如活动线程数和其他参数以适应您的环境和系统。

【讨论】:

  • 如果您有时间阅读几个小时,这可能会有所帮助hadoop.apache.org
  • @Abraham hadoop 一切都很好,但你必须需要它的额外开销......在 OP 的情况下,这是值得怀疑的。
  • @RoshanJha 看到我的回答;使用 JDK 的内置 Executors 类创建这样一个执行器非常容易。事实上,你最困难的任务是创建一个Runnable 来处理一个文件……JDK 有所有必要的类来为你完成这项工作(线程安全等)。
【解决方案2】:

最重要的是,您必须编写程序,对其进行分析,然后查看瓶颈在哪里。 磁盘 I/O 操作很可能会成为瓶颈,再多的多线程也无法解决您的问题。

在这种情况下,使用两个(三个?四个?)单独的硬盘驱动器可能会比最好的多线程解决方案产生更多的速度增益。

此外,一般规则是您应该只有在您有工作代码并且您真正知道要优化什么时才优化您的应用程序。简介,简介,简介。

写的时候考虑到未来的多线程优化是可以的;架构应该足够灵活,以支持未来的优化。

【讨论】:

  • 也许你是对的,我只是在等待一个好的开始。
  • @RoshanJha 我的观点是,首先编写一个简单的应用程序版本,然后对其进行测试、分析,然后考虑优化。 过早的优化是编程中万恶之源(或至少是大部分) -- Donald Knuth
【解决方案3】:

这里没有过多介绍您的硬件环境;但基本的解决方案是使用固定大小的ExecutorService,其大小首先是执行单元的数量:

private static final int NR_CPUS = Runtime.getRuntime().availableProcessors();

// Then:

final ExecutorService executor = Executors.newFixedThreadPool(NR_CPUS);

然后,对于每个文件,您可以创建一个Runnable 来处理它,并使用其.execute() 方法将其提交到线程池。

注意.execute()是异步的;如果提交的runnable现在不能运行,它将被排队。

【讨论】:

  • 嗯,应该吗?这就是问题所在。目前,JVM 本身唯一可用的可靠指标是执行单元的数量。这种池可能太大或太小的可能性不为零,但无论如何,这是一个很好的起点。在 运行时 适当地调整池的大小是一项艰巨的任务……甚至运行时条件也可能发生变化。但是这样一个池是一个安全的赌注,工作最终会完成......
【解决方案4】:

..听起来像是数据集成所需的典型批处理应用程序。虽然,我不打算在不完全了解您的需求的情况下抛出超链接,但是,您可能需要一个应该在单个 VM 中工作的解决方案,并且在一段时间内您希望将解决方案扩展到多个 VM/机器。并且可能我们一开始就没有处理 PB 的数据。尝试 Spring Batch 不仅可以解决给定上下文中的问题,您还将学习如何构建您的想法(想想词汇!)解决类似的问题..

【讨论】:

    【解决方案5】:

    作为起点,我将创建一个 IO 线程和一个 CPU 线程池。 IO 线程读取文本文件并将它们offers 到BlockingQueue,而CPU 线程take 来自BlockingQueue 的文件并处理它们。然后分析应用程序以查看应该使用多少 CPU 线程来与 IO 线程保持同步(您也可以动态确定这一点,例如,从一个 CPU 线程开始并在 BlockingQueue 的大小超过阈值时启动另一个 CPU 线程,可能大约 20 个文件)。您可能会发现只需要一个 CPU 线程就可以与 IO 线程保持同步,在这种情况下,您的程序是 IO 绑定的,您需要例如将文本文件彼此相邻放置在磁盘上(以便您可以对除第一个文件之外的所有文件使用顺序读取)或将它们放在单独的磁盘上以加速应用程序;一个想法是将文件压缩在一起并使用ZipInputStream 读取它们 - 这将减少读取文件时的磁盘寻道次数,也将减少您需要读取的数据量

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-16
      • 2013-09-11
      • 1970-01-01
      • 1970-01-01
      • 2013-10-29
      • 2012-01-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多