У меня есть сценарий производителя-потребителя, где производители производят намного быстрее, чем потребители могут потреблять. Как правило, решение состоит в том, чтобы блокировать производителей, поскольку сценарий производителя/потребителя работает так же быстро, как и самый медленный компонент. Дросселирование или блокирование производителей - не - хорошее решение, потому что наше приложение обеспечивает достаточно времени, чтобы потребители могли догнать их позже.Реализация Java «Tiered Queue» для быстрых Производители, медленные потребители
Вот диаграмма, изображающая полную «фаза» в нашем приложении по сравнению с более общим сценарием:
Our Application Common Scenario
2N +--------+--------+
|PPPPPPPP|oooooooo| P = Producer
|PPPPPPPP|oooooooo| C = Consumer
N +--------+--------+ N +--------+--------+--------+ o = Other Work
|CPCPCPCP|CCCCCCCC| |CPCPCPCP|CPCPCPCP|oooooooo| N = number of tasks
|CPCPCPCP|CCCCCCCC| |CPCPCPCP|CPCPCPCP|oooooooo|
------------------- ----------------------------
0 T/2 T 0 T/2 T 3T/2
Идея заключается в том, чтобы максимизировать пропускную способность, не препятствуя производитель.
Данные, с которыми работают наши задачи, легко сериализуются, поэтому я планирую внедрить решение для файловой системы для распространения всех задач, которые не могут быть немедленно выполнены.
Я использую Java ThreadPoolExecutor
с BlockingQueue
с максимальной емкостью, чтобы гарантировать, что у нас не закончится память. Проблема заключается в реализации такой «многоуровневой» очереди, где задачи, которые могут быть поставлены в очередь в памяти, выполняются немедленно, в противном случае данные помещаются в очередь на диске.
Я придумал два возможных решения:
- Реализовать
BlockingQueue
с нуля, используя реализациюLinkedBlockingQueue
илиArrayBlockingQueue
в качестве ссылки. Это может быть так же просто, как копирование реализации в стандартной библиотеке и добавление файловой системы для чтения/записи. - Продолжайте использовать стандартную реализацию
BlockingQueue
, внесите отдельный файлFilesystemQueue
для хранения моих данных и с использованием одного или нескольких потоков для удаления файлов, создайтеRunnable
s и обнулите их, используяThreadPoolExecutor
.
Есть ли они в разумных пределах и есть ли потенциально лучший подход?