Параллельная версия очереди нуждается в исключениях

#java #multithreading #concurrency #queue #blockingqueue

#java #многопоточность #параллелизм #очередь #blockingqueue

Вопрос:

Я пишу пользовательскую очередь, реализующую интерфейс queue. Эта реализация потокобезопасна и блокируется в определенных случаях.

В обычном интерфейсе очереди не упоминаются исключения, поэтому я не могу InterruptedException использовать их в своей реализации.

Я вижу два решения этой проблемы, но оба они не очень удовлетворяют:

  1. Удалите интерфейс очереди и генерируйте исключения. Это делает код непригодным для использования во внешнем программном обеспечении, для которого требуется очередь.
  2. Бросьте RuntimeException , это приведет к множеству очень неожиданных программных действий, которыми я не хочу рисковать.

Каким-то образом таким реализациям, как ArrayBlockingQueue удается реализовать Queue и BlockingQueue . Это правильный путь, или в чем здесь хитрость?

Комментарии:

1. Если вашему коду необходимо создать исключение, вам придется сделать это с помощью a RuntimeException . Если нет, то вам придется оправиться от исключения и повторить попытку или что-то в этом роде. Я не вижу здесь простого ответа. В случае InterruptedException , я обычно просто делаю Thread.currentThread().interrupt() , а затем выхожу из потока.

2. какие методы конкретно вас беспокоят?

3. Из любопытства, не могли бы вы поделиться своим вариантом использования, в котором ни одна из существующих параллельных коллекций не работает для вас?

4. Я пишу BoundedBlockingQueue, принимающий любой тип очереди в качестве аргумента. Я нашел только реализацию scala, поэтому я пишу java. Я особенно хочу предложить функцию для изменения привязки во время выполнения.

5. Для дальнейшего использования: An ArrayBlockingQueue всегда ограничен, но емкость не может быть изменена во время выполнения. Аналогично, a LinkedBlockingQueue может быть ограничено, но все равно не позволяет изменять емкость. Моя интуиция подсказывает мне, что LinkedBlockingQueue это было бы хорошим кандидатом для изменения, чтобы получить желаемое поведение.

Ответ №1:

Если вы реализуете Queue , который, возможно, потребуется выбросить InterruptedException , то я предполагаю, что вы действительно хотите реализовать BlockingQueue. Если вы прочитаете javadoc для этого интерфейса, вы поймете, что разработчики языка Java в основном сказали, что в контексте a BlockingQueue обычные Queue операции будут либо успешными, либо завершатся неудачей немедленно. Queue Интерфейс обеспечивает выдачу, IllegalStateException если add метод не может быть выполнен успешно, или возврат false , если offer метод завершается с ошибкой. Новые методы put и take , а также перегруженный вариант offer и poll вводятся BlockingQueue интерфейсом для операций, которые могут блокировать и поэтому должны вызывать InterruptedException .

Ответ №2:

Вы должны выбрать первый вариант.

Когда люди хотят иметь под рукой очередь (интерфейс), они будут ожидать, что очередь будет работать определенным образом. Поведение указано в интерфейсе, и клиенту не нужно беспокоиться о реализации или вносить изменения при переключении.

Это не относится к вашей очереди, если вы реализуете этот интерфейс, но создаете исключение во время выполнения, вы неожиданным образом нарушите ожидания вашего клиента. Иностранное программное обеспечение запрашивает очередь именно потому, что они не хотят, чтобы их «обманули», чтобы получить что-то не заменимое.

Лучше сделать это явным, не реализуя Queue, если только вы не можете прозрачно обрабатывать прерываемое исключение внутри вашего объекта.