(这里曾提出类似的问题Java XPathFactory thread-safety,但给出的答案是错误的,因为它忽略了文档指出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。还有一个约束,我需要在单例(特别是Apache Camel Processor)内部使用XPath。
答案 0 :(得分:3)
您可以放弃JAXP / DOM领域,而转而使用Saxon,在那里将多线程更仔细地整合到API设计中:
与DOM不同,一旦文档构建完成,Saxon本机树实现是线程安全的。您还将获得XPath 3.1作为奖励。
使用设置程序方法配置XPathCompiler后,它是线程安全的
XPathExpression(通过使用XPathCompiler编译表达式来创建)是线程安全的(可以在多个线程中同时执行)
XPathSelector(通过加载XPathExpression形成)不是线程安全的;只能评估一次。
答案 1 :(得分:2)
我认为
XPathFactory.newInstance()
(静态方法)不应同时被调用。它不是线程安全的。
该文档的解释可能有所不同:线程安全性和可重入性是不同的属性,因此XPathFactory.newInstance()
可能是线程安全的,但不可重入。 递归一词似乎很关键;但是句子结构很难解析。如果不仔细检查代码,则围绕任何newInstance
调用的同步似乎是使用它们的唯一安全方法。请注意,Java 9添加了newDefaultInstance
方法,该方法似乎是线程安全的。
我认为
XPath.evaluate
和XPathExpression.evaluate
不应同时被调用。它们不是线程安全的。
同意。文档明确指出这些方法既不是线程安全的也不是可重入的。
答案 2 :(得分:0)
文档似乎集中于对象,而不是newInstance调用。这是您引用的部分;我增加了一些重点:
XPathFactory类不是线程安全的。换句话说,应用程序负责确保在任何给定时刻最多有一个线程正在使用 XPathFactory对象。
并且:
XPath对象不是线程安全的,也不是可重入的。
请注意,它引用的是现有对象。 XPathFactory.newInstance是静态方法;它是静态方法。它不能在现有的XPathFactory对象上运行。在调用它的时刻,没有对象可以在线程之间共享。
文档指出,现有XPath和XPathFactory对象的非静态方法不是线程安全的。并不是说您不能在不同的线程中创建它们,只是说您不能在不同的线程中使用对象(除非您通过同步或锁定来保护该用法)。
更新:“在调用newInstance方法之一时,应用程序可能不会尝试递归调用newInstance方法”可能是指并发XPathFactory.newInstance调用,但我认为“递归”的存在表示特定的newInstance调用可能不会调用对newInstance的另一个调用。从理论上讲,如果您使用工厂类的名称来调用three-argument newInstance method,而工厂类本身会尝试调用newInstance。