Как использовать XPath в поточно-ориентированном и эффективном режиме? - PullRequest
0 голосов
/ 03 января 2019

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

Из XPathFactory Javadoc мы имеем:

Класс XPathFactory не является поточно-ориентированным.Другими словами, приложение должно гарантировать, что не более одного потока использует объект XPathFactory в любой данный момент.Реализациям рекомендуется помечать методы как синхронизированные, чтобы защитить себя от неработающих клиентов.

XPathFactory не является повторно входящим.В то время как один из методов newInstance вызывается, приложения могут не пытаться рекурсивно вызывать метод newInstance, даже из того же потока.

Так что из приведенной выше цитаты я понимаю, что XPathFactory.newInstance() (статический метод) не должен вызываться одновременно.Это не потокобезопасно.

Фабрика возвращает объекты XPath, которые имеют этот XPath Javadoc :

Объект XPath не является потоковымбезопасно и не реентерабельноДругими словами, приложение несет ответственность за то, чтобы один объект XPath не использовался из более чем одного потока в любой момент времени, и хотя метод оценки вызывается, приложения не могут рекурсивно вызывать метод оценки.

Из приведенной выше цитаты я понимаю, что XPath.evaluate и XPathExpression.evaluate не должны вызываться одновременно.Они не поточнобезопасны.

Обычно, когда я имею дело с классами, не поточнобезопасными, я просто использую локальные переменные, но потому что XPathFactory.newInstance() не поточнобезопасен, иэто статический метод, я не уверен, как использовать его безопасно и эффективно.Думаю, я мог бы синхронизировать вызовы с newInstance, но я беспокоюсь о производительности, потому что мое приложение является приложением маршрутизации сообщений XML.(В моих тестах дыма newInstance это занимает ~ 0,4 миллисекунды.)

Я не могу найти никаких примеров использования Java XPath в поточно-ориентированном режиме, и я не уверен, что знаю, какиспользуйте XPath потокобезопасным, но эффективным способом.У меня также есть ограничение на использование XPath внутри синглтона (в частности, Apache Camel Processor ).

Ответы [ 3 ]

0 голосов
/ 03 января 2019

Я так понимаю, XPathFactory.newInstance() (статический метод) не должен вызываться одновременно.Он не является потокобезопасным.

Эта документация может интерпретироваться по-разному: потокобезопасность и повторный вход являются разными атрибутами, поэтому XPathFactory.newInstance() может быть поточно-безопасным, но не входящим.Слово рекурсивно кажется ключевым;но структуру предложения трудно разобрать.Без подробного рассмотрения кода синхронизация вокруг любых вызовов newInstance кажется единственным безопасным способом их использования.Обратите внимание, что в Java 9 добавлен метод newDefaultInstance, который кажется тривиально поточно-ориентированным.

Я предполагаю, что XPath.evaluate и XPathExpression.evaluate не должны вызываться одновременно.Они не являются поточно-ориентированными.

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

0 голосов
/ 03 января 2019

Вы можете отказаться от мира JAXP / DOM и перейти на Saxon, где многопоточность гораздо более тщательно интегрирована в дизайн API:

  • В отличие от DOM, реализации саксонского собственного дерева являются поточно-ориентированными после завершения построения документа. Вы также получаете XPath 3.1 в качестве бонуса.

  • XPathCompiler является поточно-ориентированным после настройки с использованием методов установки

  • XPathExpression (созданное путем компиляции выражения с использованием XPathCompiler) является поточно-ориентированным (его можно выполнять одновременно в нескольких потоках)

  • XPathSelector (сформированный путем загрузки XPathExpression) не является поточно-ориентированным; оно должно оцениваться только один раз.

0 голосов
/ 03 января 2019

Документация фокусируется на объектах, а не на вызовах newInstance.Вот части, которые вы процитировали;Я добавил некоторые акценты:

Класс XPathFactory не является поточно-ориентированным.Другими словами, приложение должно гарантировать, что не более одного потока использует объект XPathFactory в любой данный момент.

И:

Объект XPath не является потокобезопасным и не может повторно входить.

Обратите внимание, что он ссылается на существующих объектов. XPathFactory.newInstance является статическимСпособ;он не работает с существующим объектом XPathFactory.В настоящий момент он вызывается, и нет объекта, который потенциально мог бы делиться между потоками.

В документации говорится, что нестатические методы существующих объектов XPath и XPathFactory не являются поточно-ориентированными.Это не значит, что вы не можете создавать их в разных потоках, просто вы не можете использовать объект в разных потоках (если вы не защищаете это использование синхронизацией или блокировками).

Обновление: Возможно, что «в то время как один из методов newInstance вызывается, приложения могут не пытаться рекурсивно вызывать метод newInstance», это может относиться к одновременным вызовам XPathFactory.newInstance, но я принимаю присутствие «рекурсивно», чтобы означать, чтоконкретный вызов newInstance может не вызывать другой вызов newInstance.Теоретически это может произойти, если вы вызовете метод newInstance с тремя аргументами с именем фабричного класса, который сам пытается вызвать newInstance.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...