Наблюдатель - BlockingQueue
-
27-10-2019 - |
Вопрос
Я использую шаблон наблюдателя и BlockingQueue, чтобы добавить несколько экземпляров. Теперь в другом методе я использую очередь, но кажется, что take () ждет вечно, хотя я делаю это так:
родовое словотогда как mDiffQueue - это LinkedBlockingQueue, и я использую его так:
родовое словоНо я думаю, что первое выражение проверяется, тогда как mDone неверно, тогда, возможно, для mDone установлено значение true (наблюдатель всегда многопоточный?), но он уже вызывает mDiffQueue.take ()? : - /
Изменить: я действительно не понимаю сейчас. Недавно я изменил его на:
родовое словоЕсли я немного подожду в отладчике, он сработает, но он также должен работать "в реальном времени", поскольку mDone инициализируется значением false и, следовательно, условие while должно быть истинным, а тело должно выполняться.
Если mDiffQueue пусто и mDone истинно, он должен пропустить тело цикла while (что означает, что очередь больше не заполняется).
Изменить: кажется, что это:
родовое словоХотя я не понимаю, почему peek () является обязательным.
Изменить:
То, что я делаю, - это итерация по дереву, и я хочу пропустить все узлы INSERTED:
родовое словоВ основном вычисление максимальной глубины или уровня в дереве без учета узлов, которые были удалены в другой ревизии дерева (для сравнительной визуализации Sunburst), но хорошо, возможно, это выходит за рамки. Просто чтобы проиллюстрировать, что я что-то делаю с узлами, которые не были вставлены, даже если я просто регулирую максимальную глубину.
С уважением,
Йоханнес
Решение
Первый совет: не создавайте кодовые коды. Вы бы зашли в тупик, если бы у LinkedBlockingQueue был некоторый метод synchronized (mDiffQueue)
; Здесь дело обстоит не так, но вам следует избегать этой практики. В любом случае, я не понимаю, почему вы сейчас синхронизируете.
Вы должны периодически "просыпаться" в ожидании, чтобы проверить, установлен ли synchronized
:
Это примерно то же самое, что и использование mDone
, но вместо этого peek
в основном ожидает наносекунду. Использование peek
называется «занятое ожидание» (ваш поток выполняет цикл while без остановки), а использование peek
называется «полузанятое ожидание» (вы позволяете потоку спать через определенные промежутки времени).
Я полагаю, что в вашем случае pool
будет выходить из цикла, если process(diff)
не относится к типу diff
. Я не уверен, что вы пытаетесь достичь именно этого. Это кажется странным, поскольку вы в основном просто задерживаете поток потребителя, пока не получите единственный элемент правильного типа, а затем ничего не делаете с ним. И вы не можете получать будущие входящие элементы, так как вы вышли из цикла while.
Другие советы
take()
- это «блокирующий вызов».Это означает, что он будет блокироваться (ждать вечно), пока что-то не окажется в очереди, затем он вернет то, что было добавлено.Конечно, если что-то стоит в очереди, оно немедленно вернется.
Вы можете использовать peek()
для возврата того, что будет возвращено take()
, то есть, peek()
возвращает следующий элемент без удаления его из очереди или возвращает код null
, если естьв очереди ничего нет.Попробуйте вместо этого в тесте использовать peek()
(но также проверьте наличие null).