Я реализовал класс Pipe
, который внутренне использует BlockingQueue
для хранения полученных данных.
Существуют две ситуации, когда BlockingQueue
блокирует вызывающий поток:
- Вызывающий поток звонит на
Dequeue()
, и очередь пуста.Он будет блокировать поток до тех пор, пока не найдется элемент для извлечения. - Вызывающий поток выполняет вызов
Enqueue()
, и очередь заполняется.Он будет блокировать поток до тех пор, пока снова не останется места для вставки данных.
Моя первоначальная идея заключалась в том, чтобы вместо того, чтобы класс Pipe
создавал экземпляр BlockingQueue
, я бы пропустил экземплярIQueue
к нему с помощью инжектора конструктора.Таким образом, при тестировании я передаю ему экземпляр NonBlockingQueue
, поэтому мне не придется беспокоиться о проблемах с многопоточностью (когда я выполняю юнит-тесты как для класса Pipe
, так и для другихклассы, которые используют Pipes
Я хотел бы просто добавить вещи в очереди и не думать о том, заполнены ли они уже и тому подобное).
Беда в том, что при этом яфактически заставляя мой Pipe
вести себя двумя совершенно разными способами, в зависимости от типа IQueue
экземпляра, который я передаю ему:
В BlockingQueue
, если очередьпусто, и вы пытаетесь извлечь что-то из него, оно будет блокироваться, пока не получит что-то.В NonBlockingQueue
это просто вызовет исключение.
В BlockingQueue
, если очередь заполнена и вы пытаетесь что-то добавить, она будет ждать, пока кто-то не выйдет из очередиэлемент, и снова есть место.Версия NonBlockingQueue
либо выдаст FullQueueException
, либо допустит «бесконечное» количество элементов.
То есть «единого контракта» не существует.Я думаю, что этот подход определенно неправильный.
Какой подход к этому более уместен?
Редактировать в Mitch:
Это используется для реализации системы Pipe & Filter: каждыйФильтр имеет входной и выходной патрубки.Каждый фильтр затем реализуется с помощью кода вида
char c;
while ((c = inputPipe.ReadChar()) != STREAM_TERMINATOR) {
//I don't have to care
//if right now there is any data. I know that if there isn't,
//the thread will block and this will continue after there is some.
...do processing
outputPipe.WriteChar(something);
}
outputPipe.WriteChar(STREAM_TERMINATOR);
, поэтому я предполагаю, что да, блокировка каналов / очередей - это то поведение, которое мне нужно.