[英]How do I assign an incrementing user ID to new users in a thread-safe manner?
[英]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.evaluate
和XPathExpression.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.evaluate
和XPathExpression.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.