java – DocumentBuilder线程是否安全?

我正在查看的当前代码库使用DOM解析器。以下5个方法重复以下代码片段:

 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 DocumentBuilder builder = factory.newDocumentBuilder();

如果包含上述代码的方法在循环中被调用,或者该方法在应用程序中被多次调用,那么我们将为每次调用此方法创建一个新的DocumentBuilderFactory实例和一个新的DocumentBuilder实例。

在DocumentBuilder工厂和DocumentBuilder实例周围创建一个单例包装是一个好主意,如下所示:

public final class DOMParser {
   private DocumentBuilderFactory = new DocumentBuilderFactory();
   private DocumentBuilder builder;

   private static DOMParser instance = new DOMParser();

   private DOMParser() {
      builder = factory.newDocumentBuilder();
   }

   public Document parse(InputSource xml) {
       return builder.parser(xml);
   }
}

如果上述单例在多个线程之间共享,是否有任何问题?如果没有,在应用程序的整个生命周期中,使用上述创建DocumentBuilderFactory和DocumentBuilder实例一次的方法会有什么性能增益?

编辑:

我们唯一可以面对的问题是如果DocumentBuilder在解析可能影响下一个XML文件解析的XML文件时保存一些状态信息。

最佳答案
有关同一事项的其他问题,请参阅评论部分。简单的回答你的问题:不,把这些课程放在一个单身不行。 DocumentBuilderFactory和DocumentBuilder都不能保证线程安全。如果你有几个线程解析XML,请确保每个线程都有自己的版本的DoumentBuilder。您只需要每个线程中的一个,因为您可以在重置它之后重新使用DocumentBuilder。

编辑一个小代码片段,显示使用相同的DocumentBuilder是不好的。使用java 1.6_u32和1.7_u05,这个代码失败了org.xml.sax.SAXException:解析时可能不会调用FWK005解析。取消对构建器的同步,它工作正常:

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        final DocumentBuilder builder = factory.newDocumentBuilder();

        ExecutorService exec = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            exec.submit(new Runnable() {
                public void run() {
                    try {
//                        synchronized (builder) {
                            InputSource is = new InputSource(new StringReader("<?xml version=\"1.0\" encoding=\"UTF-8\" ?><俄语>данные</俄语>"));
                            builder.parse(is);
                            builder.reset();
//                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        exec.shutdown();

所以这里是你的答案 – 不要从多个线程调用DocumentBuilder.parse()。是的,这个行为可能是JRE具体的,如果你要起诉IBM的java或者JRockit或者给它一个不同的DocumentBuilderImpl,那么它可能会运行得很好,但是对于默认的xerces实现,它不会。

转载注明原文:java – DocumentBuilder线程是否安全? - 代码日志