Java 随着线程数的增加,在HDD中写入文件的速度会变慢

Java 随着线程数的增加,在HDD中写入文件的速度会变慢,java,multithreading,Java,Multithreading,我正在使用ExecutorService创建一个多线程环境。我所有的线程都在做同样的事情。 他们从数据库中获取数据,使用itext准备PDF,并在D驱动器中的某个位置写入PDF。 但我注意到一件奇怪的事。随着线程数量的增加,端到端的进程会变慢。 对于1个线程-1小时内生成4000 pdf 对于2个线程-1小时内生成3500 pdf 对于3个线程-1小时内生成3200 pdf 对于4个线程-1小时内生成3000 pdf 通过使用logger,可以清楚地看到,从DB获取数据非常快,瓶颈是PDF写入操

我正在使用ExecutorService创建一个多线程环境。我所有的线程都在做同样的事情。 他们从数据库中获取数据,使用itext准备PDF,并在D驱动器中的某个位置写入PDF。 但我注意到一件奇怪的事。随着线程数量的增加,端到端的进程会变慢。 对于1个线程-1小时内生成4000 pdf 对于2个线程-1小时内生成3500 pdf 对于3个线程-1小时内生成3200 pdf 对于4个线程-1小时内生成3000 pdf

通过使用logger,可以清楚地看到,从DB获取数据非常快,瓶颈是PDF写入操作

我在某个地方读到,在windows中,同时在同一目录下写入多个文件比顺序写入要慢。 如果为真,我还可以实现什么逻辑来获得更高的性能。 多谢各位

环境详情 操作系统-Windows 7,32位 内存-3 GB 处理器核心i3 JDK-1.6 DB-PostgreSql 9.3
PDF的大小-在500KB和2MB之间变化,写入HDD是一个IO阻塞操作,因此使用多线程处理不会获得任何好处。使用HDD,您将实际体验到减速。如果您切换到SSD,那么您在进行多线程磁盘访问时可能不会遇到速度减慢(或者至少会比使用HDD时慢),但也不会有任何改进

如果您有RAID,情况可能会有所不同,但这取决于RAID的类型

要提高场景中的性能,您应该以以下方式拆分线程上的工作: 1) 有一个IO线程用于从磁盘读/写(或者有一个IO线程用于读,另一个IO线程用于写,这样会更好)。 2) 有单独的计算线程。此线程不应在磁盘上执行任何IO操作


IO线程只需从磁盘读取数据并将数据传递到队列(我们称之为“输入队列”)。然后“计算线程”从“输入队列”中提取数据,对其进行处理,并将结果放入另一个队列(我们称之为“结果队列”)。然后IO线程可以从“结果队列”中提取数据并将其写入磁盘

HDD一次只能写入磁盘的一部分,因此,如果您有多个不同的线程(甚至进程)同时写入,则磁盘必须四处移动磁头,在此处向文件a写入一位,在此处向文件B写入一位,等等。这就是为什么将此任务拆分为线程实际上会比较慢的原因,你让硬盘更难工作


如果您有任何CPU密集型任务,它们经常可以跨多个线程进行多路复用,以在任何现代CPU上获得好处,但是一旦您处理像特定HDD这样的单一资源,在这方面,你最好只使用一个线程。

我认为这是因为编写pdf文件是IO操作,它会阻塞,因此它成为线程的瓶颈。我们可能有一个线程用于编写,其他线程用于准备数据。我想知道writer线程是否能跟上进度。我认为问题在于,线程有一个调度机制。线程只是一种并行工作。事实上,这只是一个序数。也许如果你使用了更多的线程,它就必须重新打开文件或重新开始写入。@MarcelHöll:在任何现代CPU上都不是。一旦有了多个内核,您就可以一次真正完成多件事情。但在这种情况下,I/O会杀死它。”…或者,有一个IO线程用于读取,另一个IO线程用于写入-因为这样会更好…”不,这仍然会导致晃动,将头部从一个地方拉到另一个地方。