#java #multithreading #concurrency #queue #blockingqueue
#java #многопоточность #параллелизм #очередь #blockingqueue
Вопрос:
Я пишу пользовательскую очередь, реализующую интерфейс queue. Эта реализация потокобезопасна и блокируется в определенных случаях.
В обычном интерфейсе очереди не упоминаются исключения, поэтому я не могу InterruptedException
использовать их в своей реализации.
Я вижу два решения этой проблемы, но оба они не очень удовлетворяют:
- Удалите интерфейс очереди и генерируйте исключения. Это делает код непригодным для использования во внешнем программном обеспечении, для которого требуется очередь.
- Бросьте
RuntimeException
, это приведет к множеству очень неожиданных программных действий, которыми я не хочу рисковать.
Каким-то образом таким реализациям, как ArrayBlockingQueue
удается реализовать Queue
и BlockingQueue
. Это правильный путь, или в чем здесь хитрость?
Комментарии:
1. Если вашему коду необходимо создать исключение, вам придется сделать это с помощью a
RuntimeException
. Если нет, то вам придется оправиться от исключения и повторить попытку или что-то в этом роде. Я не вижу здесь простого ответа. В случаеInterruptedException
, я обычно просто делаюThread.currentThread().interrupt()
, а затем выхожу из потока.2. какие методы конкретно вас беспокоят?
3. Из любопытства, не могли бы вы поделиться своим вариантом использования, в котором ни одна из существующих параллельных коллекций не работает для вас?
4. Я пишу BoundedBlockingQueue, принимающий любой тип очереди в качестве аргумента. Я нашел только реализацию scala, поэтому я пишу java. Я особенно хочу предложить функцию для изменения привязки во время выполнения.
5. Для дальнейшего использования: An
ArrayBlockingQueue
всегда ограничен, но емкость не может быть изменена во время выполнения. Аналогично, aLinkedBlockingQueue
может быть ограничено, но все равно не позволяет изменять емкость. Моя интуиция подсказывает мне, чтоLinkedBlockingQueue
это было бы хорошим кандидатом для изменения, чтобы получить желаемое поведение.
Ответ №1:
Если вы реализуете Queue
, который, возможно, потребуется выбросить InterruptedException
, то я предполагаю, что вы действительно хотите реализовать BlockingQueue. Если вы прочитаете javadoc для этого интерфейса, вы поймете, что разработчики языка Java в основном сказали, что в контексте a BlockingQueue
обычные Queue
операции будут либо успешными, либо завершатся неудачей немедленно. Queue
Интерфейс обеспечивает выдачу, IllegalStateException
если add
метод не может быть выполнен успешно, или возврат false
, если offer
метод завершается с ошибкой. Новые методы put
и take
, а также перегруженный вариант offer
и poll
вводятся BlockingQueue
интерфейсом для операций, которые могут блокировать и поэтому должны вызывать InterruptedException
.
Ответ №2:
Вы должны выбрать первый вариант.
Когда люди хотят иметь под рукой очередь (интерфейс), они будут ожидать, что очередь будет работать определенным образом. Поведение указано в интерфейсе, и клиенту не нужно беспокоиться о реализации или вносить изменения при переключении.
Это не относится к вашей очереди, если вы реализуете этот интерфейс, но создаете исключение во время выполнения, вы неожиданным образом нарушите ожидания вашего клиента. Иностранное программное обеспечение запрашивает очередь именно потому, что они не хотят, чтобы их «обманули», чтобы получить что-то не заменимое.
Лучше сделать это явным, не реализуя Queue, если только вы не можете прозрачно обрабатывать прерываемое исключение внутри вашего объекта.