tgoop.com/Java_Iibrary/1717
Last Update:
У тебя несколько потоков-продюсеров, которые кладут элементы в очередь, и несколько потоков-консьюмеров, которые их оттуда забирают.
Если очередь полная, продюсеры ждут.
Если очередь пустая, консьюмеры ждут.
Как реализовать такую потокобезопасную ограниченную очередь?
На первый взгляд задача простая, но на деле она проверяет, насколько хорошо ты понимаешь синхронизацию и координацию потоков.
Ответ
Мы держим фиксированного размера буфер (Deque).
Продюсеры при вызове put ждут, если буфер заполнен.
Консьюмеры при вызове take ждут, если буфер пуст.
Когда продюсер кладёт элемент, он сигналит ожидающему консьюмеру.
Когда консьюмер забирает элемент, он сигналит ожидающему продюсеру.
Ожидание всегда делается внутри while, чтобы поток после пробуждения перепроверил условие.
Флаг close запрещает новые вставки и будит всех, чтобы они завершились корректно.
Предпочтительный способ это использовать ReentrantLock. Это как synchronized, только с большим контролем. Один и тот же поток может захватить его несколько раз без дедлока. Он позволяет создавать Condition-объекты — это очереди ожидания, привязанные к замку. Здесь удобно завести две: notFull и notEmpty, чтобы продюсеры и консьюмеры ждали и сигналили точно по ситуации.

