繁体   English   中英

如何以线程安全且高效的方式使用XPath?

[英]How do I use XPath in a thread-safe and efficient manner?

(这里有一个类似的问题, Java XPathFactory线程安全 ,但给定的答案是不正确的,因为它忽略了文档声明XPathFactory.newInstance()不是线程安全的事实。)

XPathFactory Javadoc ,我们有:

XPathFactory类不是线程安全的。 换句话说,应用程序有责任确保在任何给定时刻最多只有一个线程正在使用XPathFactory对象。 鼓励实现将方法标记为同步以保护自己免受破坏的客户端的影响。

XPathFactory不可重入。 在调用其中一个newInstance方法时,应用程序可能不会尝试以递归方式调用newInstance方法,即使是在同一个线程中也是如此。

所以从上面的引用,我认为不应该同时调用XPathFactory.newInstance() (静态方法)。 它不是线程安全的。

工厂返回XPath对象,它有这个XPath Javadoc

XPath对象不是线程安全的,不可重入。 换句话说,应用程序负责确保在任何给定时间不从多个线程使用一个XPath对象,并且在调用evaluate方法时,应用程序可能不会递归调用evaluate方法。

从上面的引用,我认为不应该同时调用XPath.evaluateXPathExpression.evaluate 它们不是线程安全的。

通常,当我处理不是线程安全的类时,我只使用局部变量,但是因为XPathFactory.newInstance()不是线程安全的,而且它是一个静态方法,我不知道如何使用它安全有效。 我想我可以同步调用newInstance ,但我担心性能,因为我的应用程序是一个XML消息路由应用程序。 (在我对newInstance冒烟测试中,需要~0.4毫秒。)

我找不到任何以线程安全方式使用Java XPath的示例,我不相信我知道如何以线程安全但有效的方式使用XPath。 我还有一个约束,我需要在单例(特别是Apache Camel处理器 )中使用XPath。

您可以放弃JAXP / DOM世界并迁移到Saxon,其中多线程更加谨慎地融入API设计:

  • 与DOM不同,一旦文档构建完成,Saxon本机树实现就是线程安全的。 您还可以获得XPath 3.1作为奖励。

  • 一旦使用其setter方法配置,XPathCompiler就是线程安全的

  • XPathExpression(通过使用XPathCompiler编译表达式创建)是线程安全的(它可以在多个线程中并发执行)

  • XPathSelector(通过加载XPathExpression形成)不是线程安全的; 它只应评估一次。

我认为不应该同时调用XPathFactory.newInstance() (静态方法)。 它不是线程安全的。

该文档可能有不同的解释:线程安全和重入是不同的属性,因此XPathFactory.newInstance()可能是线程安全的但不可重入。 递归这个词似乎是关键; 但句子结构难以解析。 如果不仔细查看代码,那么围绕任何newInstance调用的同步似乎是使用它们的唯一安全方法。 请注意,Java 9添加了newDefaultInstance方法,该方法看起来非常简单。

我认为不应该同时调用XPath.evaluateXPathExpression.evaluate 它们不是线程安全的。

同意。 文档明确指出这些方法既不是线程安全的,也不是可重入的。

文档似乎关注对象,而不是newInstance调用。 以下是你引用的部分; 我增加了一些重点:

XPathFactory类不是线程安全的。 换句话说,应用程序有责任确保在任何给定时刻最多只有一个线程正在使用XPathFactory对象

和:

XPath对象不是线程安全的,不可重入。

请注意,它指的是现有对象。 XPathFactory.newInstance是一个静态方法; 它不能在现有的XPathFactory对象上运行。 在调用它的那一刻,没有任何对象可以在线程之间共享。

该文档说明现有XPath和XPathFactory对象的非静态方法不是线程安全的。 它并不是说您不能在不同的线程中创建它们,只是不能在不同的线程中使用对象(除非您使用同步或锁保护该用法)。

更新:有可能“当调用newInstance方法之一时,应用程序可能不会尝试递归调用newInstance方法”可能会引用并发XPathFactory.newInstance调用,但我采用“递归”存在来表示某个特定的newInstance调用可能不会调用另一个对newInstance的调用。 理论上,如果您调用具有工厂类名称的三参数newInstance方法本身会尝试调用newInstance,则会发生这种情况。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM