Этот вопрос относится к последней версии Java.
30 потоков-производителей помещают строки в абстрактную очередь. Один поток записи появляется из той же очереди и записывает строку в файл, который находится на жестком диске RAID со скоростью вращения 5400 об/мин. Данные передаются со скоростью примерно 111 МБ/с и извлекаются/записываются со скоростью примерно 80 МБ/с. Программа живет 5600 секунд, этого достаточно, чтобы в очереди накопилось около 176 ГБ данных. С другой стороны, я ограничен в общей сложности 64 ГБ основной памяти.
Мой вопрос: какой тип очереди я должен использовать?
Вот что я пробовал до сих пор.
1) ArrayBlockingQueue
. Проблема с этой ограниченной очередью заключается в том, что независимо от начального размера массива у меня всегда возникают проблемы с живучестью, как только он заполняется. Фактически через несколько секунд после запуска программы top
сообщает только об одном активном потоке. Профилирование показывает, что в среднем потоки-производители тратят большую часть своего времени на ожидание освобождения очереди. Это не зависит от того, использую ли я политику справедливого доступа (со вторым аргументом в конструкторе, установленным в true).
2) ConcurrentLinkedQueue
. Что касается живучести, эта неограниченная очередь работает лучше. Пока у меня не закончится память, примерно через семьсот секунд все тридцать потоков-производителей будут активны. Однако после того, как я превыслю лимит в 64 ГБ, все станет невероятно медленным. Я предполагаю, что это связано с проблемами пейджинга, хотя я не проводил никаких экспериментов, чтобы доказать это.
Я вижу два выхода из своего положения.
1) Купи SSD. Надеюсь, увеличение скорости ввода-вывода поможет.
2) Сжать выходной поток перед записью в файл.
Есть ли альтернатива? Я что-то упустил в том, как построена/используется любая из вышеперечисленных очередей? Есть ли более умный способ их использования? В книге Java Concurrency in Practice предлагается ряд политик насыщения (раздел 8.3.3) на случай, если ограниченные очереди заполняются быстрее, чем они могут быть исчерпаны, но, к сожалению, ни одна из них — прерывание, выполнение вызывающего объекта и два отбрасывания политики --- применяются в моем сценарии.