Я хотел бы знать, какой был бы лучший механизм для реализации нескольких сценариев Producer - single Consumer, где мне нужно постоянно обновлять текущее количество необработанных запросов.Потребитель-производитель с высоким разрешением
Моя первая мысль была использовать ConcurrentLinkedQueue:
public class SomeQueueAbstraction {
private Queue<SomeObject> concurrentQueue = new ConcurrentLinkedQueue<>();
private int size;
public void add(Object request) {
SomeObject object = convertIncomingRequest(request);
concurrentQueue.add(object);
size++;
}
public SomeObject getHead() {
SomeObject object = concurrentQueue.poll();
size--;
}
// other methods
Проблема с этим состоит в том, что я должен явно синхронизировать add
и size ++
, а также на poll
и size--
, чтобы всегда иметь точные size
, что делает ConccurentLinkedQueue
бессмысленно для начала.
Каким будет наилучший способ достижения максимально возможной производительности при сохранении согласованности данных?
Вместо этого я использую ArrayDequeue
и явно синхронизирую, или есть лучший способ достичь этого?
Существует своего родом подобный вопрос/ответ здесь:
java.util.ConcurrentLinkedQueue
, где обсуждаются, как композиционные операции на ConcurrentLinkedQueue
, естественно, не атомный, но нет прямого ответа, что это лучший вариант для данного сценарий.
Примечание: Я вычисляю размер явно, потому что временная сложность для встроенного метода .size() - это O (n).
Note2: Я также обеспокоен тем, что метод getSize(), который я явно не написал, добавит еще больше конфликтов. Его можно было бы назвать относительно часто.
Я ищу наиболее эффективный способ обработки нескольких производителей - один потребитель с частыми вызовами getSize().
Альтернативное предложение: Если в структуре SomeObject был элемент, то я мог бы получить текущий размер из ConcurrentLinkedQueue.poll(), и только блокирование должно выполняться внутри механизма для создания такого идентификатора. Теперь добавить и получить можно правильно использовать без дополнительной блокировки. Как это будет в качестве альтернативы?
Имеет ли размер() метод всегда должен быть _exactly_ правильно?(Подсказка: что произойдет, если поток A вызывает size() и возвращает точно правильный ответ, но тогда, когда поток A принимает какое-то решение, основанное на размере, какой-то другой поток B пробирается и меняет размер?) –
Поскольку вы пытаются сохранить количество необработанных запросов на низком уровне, почему вас беспокоит размер O (n)? Как часто вам нужно знать размер? – NamshubWriter