我可以安全地从多个线程查询带有xpath表达式的DOM Document吗?

Dan*_*Dan 3 java xml concurrency xpath dom4j

我计划在多个线程可以查询文档的应用程序中使用dom4j DOM Document作为静态缓存.考虑到文档本身永远不会改变的帐户,从多个线程查询它是否安全?

我写了下面的代码来测试它,但我不确定它确实证明操作是安全的吗?

    package test.concurrent_dom;

    import org.dom4j.Document;
    import org.dom4j.DocumentException;
    import org.dom4j.DocumentHelper;
    import org.dom4j.Element;
    import org.dom4j.Node;

    /**
     * Hello world!
     *
     */
    public class App extends Thread
    {
        private static final String xml = 
            "<Session>"
                + "<child1 attribute1=\"attribute1value\" attribute2=\"attribute2value\">"
                + "ChildText1</child1>"
                + "<child2 attribute1=\"attribute1value\" attribute2=\"attribute2value\">"
                + "ChildText2</child2>" 
                + "<child3 attribute1=\"attribute1value\" attribute2=\"attribute2value\">"
                + "ChildText3</child3>"
            + "</Session>";

        private static Document document;

        private static Element root;

        public static void main( String[] args ) throws DocumentException
        {
            document = DocumentHelper.parseText(xml);
            root = document.getRootElement();

            Thread t1 = new Thread(){
                public void run(){
                    while(true){

                        try {
                            sleep(3);
                        } catch (InterruptedException e) {                  
                            e.printStackTrace();
                        }

                        Node n1 = root.selectSingleNode("/Session/child1");                 
                        if(!n1.getText().equals("ChildText1")){                     
                            System.out.println("WRONG!");
                        }
                    }
                }
            };

            Thread t2 = new Thread(){
                public void run(){
                    while(true){

                        try {
                            sleep(3);
                        } catch (InterruptedException e) {                  
                            e.printStackTrace();
                        }

                        Node n1 = root.selectSingleNode("/Session/child2");                 
                        if(!n1.getText().equals("ChildText2")){                     
                            System.out.println("WRONG!");
                        }
                    }
                }
            };

            Thread t3 = new Thread(){
                public void run(){
                    while(true){

                        try {
                            sleep(3);
                        } catch (InterruptedException e) {                  
                            e.printStackTrace();
                        }

                        Node n1 = root.selectSingleNode("/Session/child3");                 
                        if(!n1.getText().equals("ChildText3")){                     
                            System.out.println("WRONG!");
                        }
                    }
                }
            };

            t1.start();
            t2.start();
            t3.start();
            System.out.println( "Hello World!" );
        }    

    }
Run Code Online (Sandbox Code Playgroud)

mdm*_*dma 5

http://xerces.apache.org/xerces2-j/faq-dom.html

不.DOM不要求实现是线程安全的.如果需要从多个线程访问DOM,则需要向应用程序代码添加适当的锁.

在没有看到实现的情况下,不可能知道是否selectSingleNode使用任何共享状态来读取DOM.我认为最安全的做法是假设它不是线程安全的.

另一种方法是使用自己的XPath处理器,例如Jaxen,它是线程安全的.

XPath对象是完全可重入且线程安全的.它们不包含用于评估的内部状态,因此可以在应用程序中轻松缓存和共享.一旦有了XPath对象,就可以将它应用于各种初始上下文,并以几种不同的方式检索结果:--- SAX路径和Jaxen简介

JAXEN Jira针对线程安全问题提供了各种修复,提供了Jaxen设计为线程安全的证据.这是一个我偶然碰到.并确认 Jaxen是其中一位作者的线程安全.

除了线程安全之外,Jaxen与模型无关 - 它适用于许多模型(W3C DOM,XOM,Dom4J,JDOM),并且可以通过实现几个接口来插入自定义模型.

我认为W3C DOM上的简单访问器和迭代器是线程安全的.但这只是一种预感,而不是一个具体的事实.如果你想100%确定,那么使用专为thread-saftey设计的DOM,例如dom4j.

一些入门资源: - 使用Jaxen的一个例子.- Jaxen常见问题主页