Java中的多线程是否需要花费大量时间来完成任务?

Java中的多线程是否需要花费大量时间来完成任务?,java,multithreading,Java,Multithreading,我必须在10个大文件(zip格式70 MB)中搜索一个字符串,并将带有搜索字符串的行打印到相应的10个输出文件中。(即,文件1输出应在输出文件1…文件2--->输出文件2中)。同一个程序对单个文件需要15分钟。但是如果使用10个线程来读取10个文件并写入10个不同的文件,它应该在15分钟内完成,但需要40分钟 我怎样才能解决这个问题。或者多线程只需要这么多时间?我想您没有使用10核cpu机器,所以您的线程并不是真正并行运行的。因此,它需要比数学上更长的时间。接下来,您必须意识到线程管理也需要一些

我必须在10个大文件(zip格式70 MB)中搜索一个字符串,并将带有搜索字符串的行打印到相应的10个输出文件中。(即,文件1输出应在输出文件1…文件2--->输出文件2中)。同一个程序对单个文件需要15分钟。但是如果使用10个线程来读取10个文件并写入10个不同的文件,它应该在15分钟内完成,但需要40分钟


我怎样才能解决这个问题。或者多线程只需要这么多时间?

我想您没有使用10核cpu机器,所以您的线程并不是真正并行运行的。因此,它需要比数学上更长的时间。接下来,您必须意识到线程管理也需要一些时间(这是不相关的)。 也许你可以加快你的文件搜索机制来获得一些速度。为此,您需要发布您的源代码。 但有人建议:

  • 您应该尽量保持文件访问计数尽可能低,因为这是最慢的操作
  • 尽量少用内存,因为如果机器开始交换内存页,速度也会显著降低
  • 由于您是在java中执行此操作的,因此您应该使用reg ex来查找字符串中的字符串,因为(据我记忆所及)这是在java中搜索字符串的最快方法

但请注意,这种措施可能会导致一个非常复杂的代码,阅读其他人或你自己在。。。比方说六个月以上,因为你不会记得你做过的每件事以及你为什么这么做(评论;)

你可能有硬盘争用,而多线程对你没有帮助。在您的情况下,您可能只需要足够的线程来保持磁盘驱动器100%的使用率

我假设硬盘是你的瓶颈,而不是CPU。如果每个线程不必为同一个硬件而争斗,那么多线程只能“更快”完成任务。因此,使用多核(CPU)和多硬盘驱动器,您将看到多线程的更好性能

我很惊讶一个文件需要15分钟

下面是我将如何设计这个。70MB不是很大。您可能会将每个70MB未压缩文件加载到内存中,每个线程一个。然后,在搜索压缩流时实时解压数据,在内存中保留少量未压缩数据。(一旦你搜索过,就扔掉它)。这将避免硬盘抖动,并允许您的CPU达到100%的使用率


如果内存有问题,那么一次从磁盘加载几MB。

并发访问文件通常会在2-3个线程后变慢,因为硬盘最终会反复尝试同时读取所有文件,类似于读取碎片整理的文件

为了避免这种情况,将工作分成文件读取器和文件解析器。文件读取器从文件中引入数据(也进行解压缩),文件解析器解析数据。您可以使用
PipedInputStream
/
pipedOutStream
将数据从文件读取器转发到文件解析器


因为您的文件是压缩的,所以读取涉及到I/O和cpu,它们可以在读取所有文件的2-4个线程之间很好地交错。对于解析文件,最简单的方法是只有一个线程从PipedInputStream读取,因此每个文件都有一个解析器线程。每个文件使用多个线程需要分割流并在块边界处处理搜索,这会使过程复杂化,在这里不需要,因为您可能有10个解析器线程和2-4个读卡器线程的足够并行性。

更多的线程很可能会使它运行得更慢,因为您的瓶颈将是磁盘IO。如果您可以先将所有数据加载到内存中,那么您会看到多个线程的速度有所提高,但仅达到#cores+1的程度,更多的只是上下文切换开销。

当您运行此功能时,您的CPU已经达到100%了吗?如果不是,有两件事

  • 如果是硬盘驱动器,您可以尝试移动到更快的硬盘驱动器、RAID0条带(数据丢失危险)或RAID5
  • 您有一个多核CPU,由于某些原因,它并不是在所有的核上运行。您可以在Windows中点击CTRL-ALT-DEL、任务管理器、性能选项卡来检查这一点。如果CPU使用历史记录在一个图表上,您就没有充分利用处理器,并且可以考虑线程。如果CPU使用率在任何地方都没有达到最大值,那么硬盘驱动器就会出现瓶颈,再多的线程也不会对性能产生多大影响。如果CPU的使用率在任何地方都是最大的,那么线程化只会使速度变慢;您需要更快的CPU来更快地运行该任务,或者需要更好的算法

    • 我猜这是一个GC问题。我猜您正在将文件一行一行地读入
      字符串中。也许您甚至正在为每一行重新编译一个正则表达式。不管怎么说,有很多内存分配,但对象寿命很短。多个线程可能会在复制到“幸存者”空间(在典型的sungc实现中)时充分利用这一点。我猜应该使用visualvm,或者一个模糊的命令行参数来监视GC的工作强度


      也可能是一个锁争用问题,但这看起来令人尴尬地平行。

      您可能想看看Tim Bray创建的项目。这听起来很像你正在做的事情,我认为它会检查你将遇到的大多数问题(如果不是所有的话)。hth

      您是否仍然希望使用一百万个线程处理一百万个文件需要15分钟?为什么一个文件需要15分钟?这段时间它在做什么?性能瓶颈是什么?70 MB 10个文件15分钟不太可能出现磁盘问题(除非它确实是碎片化的)。如果搜索文本,indexOf(startIdx,pattern)比regex快得多。