Comments 9
Крайне неудачное название. Сложно нагуглить, мешается бизнес-термин.
Второй вопрос. Чем это решение лучше просто переменной в объекте Consumer?
Чем это решение лучше просто переменной в объекте Consumer?
Тем, что Publisher не должен знать о реализации Consumer, о том есть ли у него эта магическая переменная, о том существует ли вообще Consumer, сколько экземпляров Consumer, какая структура очереди (например либо это очередь классическая, либо множество реплик очереди каждая из которых к своему экземпляру Consumer'а).
Поэтому Publisher просто отправляет событие EOF (End-Of-File/ End-Of-Stream / End-Of-Data) и всё.
но публишер знает об очереди, в которую он складывает сообщения. Что если сделать флаг окончания работы публишера в очереди?
И фактически этот флаг и станет тем самым "poison pill" который в этой статье и описан. Только это приведет еще к тому, что надо будет мониторить этот флаг. Добавляется также проблема с тем, что если consumer вошел в блокирующее ожидание на очереди, это ожидание нужно прервать при выставлении флага.
И вишенка на торте - когда система распределенная и publisher и consumer работают в разных процессах и на разных серверах, и тогда вы с флагом вообще задолбаетесь.
С другой стороны не надо проверять каждое сообщение. Если сообщение есть - просто обрабатываем его, а вот если нет, то надо проверить флаг. И ждем же мы все равно с таймаутом - вот по его окончании и проверим флаг, и прервемся если больше сообщений не ожидается.
Распределенные сервера - это и с отравленным сообщением не так просто - например, что делать, если есть несколько publisher-ов? Если один отправит сообщение eof, то все consumer-ы закончат работу? Или что будет если вдруг сообщения встанут в очередь не по порядку и poison pill сработает раньше чем нужно?
Но ведь задача именно в том, чтобы сторонный объект мог остановить именно этот объект Runnable. Усложнение для программиста в том, что он должен связать через левую очередь взаимодействие Runnable и контролирующий его объект. А если этих палблишеров-консумеров в программе куча? А если чайник воспользуется имеющиейся очередью для отправки сообщения runnable-объекту? А потом эта очередь, предназначавшаяся изначально для чего-то другого, будет некаккуратно переделана? А как обеспечивать пересылку киллер-сообщения конкретному runnable-объекту? Вот посмотрите, сколько сложностей вы вывалили на голову коллегам? При том, что задача решается просто переменной в runnalbe-объекте.
При том, что "publisher" все-равно должен знать о реализации "Consumer", хотя бы по формату передаваемых данных, по константам команд, которые воспринимает runnable-объект. Опять же тип очереди - появляется зависимость от типа очереди и у runnable-объекта и у его контролера. Ладно вы разрабатываете и то и другое, и сделали через интерфейс. А если разработчик потребителя не вы?
"Магическая переменная", бгг. А знать, если ли у консумера "магическая очередь", не надо? И не надо знать формат и тип сообщений и константы? И не надо знать, как ее задавать у приемника-передатчика, нужно ли ее создавать, либо надо шариться в приложении искать, есть объект очереди, связан ли он с нужным runnable? Видите, насколько больше приходится не знать?
Я бы этим термином NaN'ы назвал в IEEE754. Оператор(число, NaN) будет NaN. Причем там предусматривается возможность дополнительную инфу закодировать, и она должна проползти через всю арифметику.
Спасибо за статью, хорошее описание методов работы. Единственное что не раскрыто - это различие между State Machine и Poison pill. Понятно, что в данной ситуации, Poison pill - это решение для потока и его самоуправления, но хотелось бы увидеть различие между ними в данной статье. А в остальном прекрасная статься, спасибо ещё раз.
Вопрос, а на чёрта?)
А почему просто продюсер не может перестать посылать сообщения?)
а как потом консьюмер запустить? Передеплоить?)
А в следующий раз вы расскажете как удобно есть пельмени попой, но тоже не объясните зачем?)
Паттерн Poison Pill в Java