在 java 中执行 IO 操作的最佳线程数是多少?

2022-09-02 03:56:27

在Goetz的“Java并发实践”中,在第101页的脚注中,他写道:“对于像这样的计算问题,如果不进行I / O并且不访问共享数据,Ncpu或Ncpu + 1线程产生最佳吞吐量;更多的线程无济于事,实际上可能会降低性能...”

我的问题是,在执行 I/O 操作(如文件写入、文件读取、文件删除等)时,是否有用于实现最大性能的线程数的准则?我知道这只是一个指导数字,因为磁盘速度和许多其他因素都会对此产生影响。

不过,我想知道:20个线程将1000个单独的文件写入磁盘的速度是否比4 cpu机器上的4个线程更快?


答案 1

在实践中,受 I/O 限制的应用程序仍然可以从多线程处理中受益匪浅,因为并行读取或写入几个文件比按顺序读取或写入几个文件要快得多。当整体吞吐量受到网络延迟的影响时,尤其如此。但这种情况也是,一个线程可以处理它读取的最后一个内容,而另一个线程则忙于读取,从而允许更高的CPU利用率。

我们可以整天谈论理论,但正确的答案是使线程数量可配置。我想你会发现,把它增加到1会提高你的速度,但也会有一个收益递减的点。


答案 2

是的,20 个线程写入磁盘的速度肯定比 4 CPU 计算机上的 4 个线程快。许多实际程序的 I/O 绑定比 CPU 绑定更多。但是,它非常详细地取决于您的磁盘,以及其他线程在最终等待这些磁盘之前正在执行的CPU工作量。

如果所有线程都只写入磁盘而不执行任何其他操作,那么很可能是 4 CPU 计算机上的 1 个线程实际上是写入磁盘的最快方法。这完全取决于您拥有多少磁盘,正在写入多少数据,以及操作系统在I / O调度方面的表现。您的具体问题表明您希望4个线程全部写入同一文件。这没有多大意义,在任何实际情况下,我都想不出这会更快。(您必须提前分配文件,然后每个线程都会 seek() 到不同的位置,并且当每个线程尝试写入一些块时,您最终只会抖动写入头。

当您受到网络约束时,多线程的优势要简单得多。即:在数据库服务器或Web浏览器等上等待。在那里,您正在等待多个外部资源。