此问题涉及Java的最新版本。Java和队列:多线程I/O的饱和问题
30生产者线程将字符串推送到抽象队列。一个写线程从同一队列中弹出并将该字符串写入驻留在5400 rpm HDD RAID阵列上的文件。数据以大约111MBps的速率推送,并以大约80MBps的速率弹出/写入。该程序持续5600秒,足以让队列中积累大约176 GB的数据。另一方面,我限制在总共64GB的主内存中。
我的问题是:我应该使用什么类型的队列?
这是我到目前为止尝试过的。
1)ArrayBlockingQueue
。这个有界的队列的问题是,无论数组的初始大小如何,我总是会在满足时立即生存活性问题。实际上,程序启动后几秒钟,top
只报告一个活动线程。分析表明,平均而言,生产者线程花费大部分时间等待队列释放。这与我是否使用公平访问策略(将构造函数中的第二个参数设置为true)无关。
2)ConcurrentLinkedQueue
。就活力而言,这个无界的队列表现更好。在内存耗尽之前,大约七百秒钟内,所有三十个生产者线程都处于活动状态。然而,在我超过了64GB的限制后,事情变得非常慢。我猜想这是因为分页问题,尽管我没有进行任何实验来证明这一点。
我预见了两种情况。
1)购买SSD。希望I/O速度的提高会有所帮助。
2)在写入文件之前压缩输出流。
是否有替代方案?我是否在构建/使用上述队列中缺少某些东西?有没有更聪明的方法来使用它们? Java Concurrency in Practice书中提出了许多饱和策略(见第8.3.3节),当有界队列填满的速度比他们可以耗尽的情况快时,但不幸的是他们中没有一个 - 中止,主叫运行和两个丢弃政策---适用于我的情况。
当您意识到磁盘是您的瓶颈,无论您如何使用该软件,磁盘的性能都是您必须解决的问题。这意味着压缩数据和/或购买更快的磁盘。请注意,您可以获得大约100美元的400 MB/s SSD。 –
如果您的生产者比您的消费者生产速度快,您必须让消费者更快或者生产者更慢。 – Raedwald
您似乎很惊讶,试图在64GB计算机上存储176GB的对象会让您的程序变慢。 – Raedwald