【问题标题】:Java XPathFactory thread-safetyJava XPathFactory 线程安全
【发布时间】:2012-02-25 00:00:29
【问题描述】:

javax.xml.XPathFactory.newInstance() 线程安全吗?

我之所以这么问,是因为我发现文档对此含糊不清。 The JDK 5 docs 根本不提线程安全;他们在JDK 6 中写道:

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

据我了解,为XPathFactory 单独实现是不安全的,但这样做应该是安全的:

XPath xPathEvaluator = XPathFactory.newInstance().newXPath();

我错过了什么吗?它是否取决于扩展它的实际类?我需要synchronize包含上述语句的方法吗?

【问题讨论】:

标签: java xml xpath thread-safety


【解决方案1】:

XPath xPathEvaluator = XPathFactory.newInstance().newXPath();

这是安全的,因为每个线程都有自己的工厂(感谢newInstance())。此处无需同步。

你不能安全地做的是只获取一次工厂,然后在不同步的情况下在线程之间共享它,例如作为单例。 XPath 实例 (xPathEvaluator) 本身也是如此。

【讨论】:

  • JAXP-XPath 设计有很多不好的地方。其中之一是 XPathFactory.newInstance() 非常昂贵;另一个是您应该在每个线程中重复调用它。另一个是您无法知道您将获得 XPath 1.0 引擎还是 XPath 2.0 引擎。问问自己你是否真的想使用这种机制:如果你知道你想要什么 XPath 引擎,那么有更好的方法来加载它。
  • 嗨 Michael,有什么更好的加载 XPath 引擎的方法?
  • 根据 Javadoc docs.oracle.com/javase/6/docs/api/javax/xml/xpath/… : XPathFactory is not re-entrant. While one of the newInstance methods is being invoked, applications may not attempt to recursively invoke a newInstance method, even from the same thread.,XPathFactory.newInstance() 是不安全的。需要同步。但是,我看了 XPathFactory 的源代码,不知道哪个操作是不安全的。
  • @aleung:“即使来自同一个线程”。所以同步在这里对你没有帮助。我不确定该警告的确切含义,但我认为它只是说您不应该在 newInstance 仍在执行时调用 newInstance (虽然不知道您将如何做到这一点)。
  • 这个答案与文档不一致。该文档明确指出“虽然正在调用 newInstance 方法之一,但应用程序可能不会尝试递归调用 newInstance 方法,即使从同一个线程也是如此。”这与 newInstance 返回的实例是否是线程安全的无关,而是关于对XPathFactory.newInstance() 的调用是否是静态方法 是否是线程安全的。两个线程很容易调用同一个静态方法@Thilo。
【解决方案2】:

“其中之一是 XPathFactory.newInstance() 非常昂贵;”

真实的陈述!我注意到对于每个调用 newInstance() 的线程,jaxp.properties 必须位于类路径中并读入:

java.lang.Thread.State: BLOCKED (on object monitor)
        at java.util.zip.ZipFile.getEntry(ZipFile.java:160)
        - locked <0x0000000968dec028> (a sun.net.www.protocol.jar.URLJarFile)
        at java.util.jar.JarFile.getEntry(JarFile.java:208)
        at sun.net.www.protocol.jar.URLJarFile.getEntry(URLJarFile.java:107)
        at sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:114)
        at sun.net.www.protocol.jar.JarURLConnection.getInputStream(JarURLConnection.java:132)
        at java.net.URL.openStream(URL.java:1010)
        at javax.xml.xpath.SecuritySupport$4.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at javax.xml.xpath.SecuritySupport.getURLInputStream(Unknown Source)
        at javax.xml.xpath.XPathFactoryFinder._newFactory(Unknown Source)
        at javax.xml.xpath.XPathFactoryFinder.newFactory(Unknown Source)
        at javax.xml.xpath.XPathFactory.newInstance(Unknown Source)
        at javax.xml.xpath.XPathFactory.newInstance(Unknown Source)

ZipFile 进行本机调用(我相信是 zlib)并解压缩 jar,这需要磁盘 IO 和处理器绑定的 zip 解压缩。在本例中,我们有 1400 多个线程在等待该锁。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-06
    • 1970-01-01
    • 2021-12-16
    • 2010-11-14
    • 2014-09-16
    • 2011-11-23
    • 2010-10-12
    • 1970-01-01
    相关资源
    最近更新 更多