Java从不同的线程读取w3c.Document

时间:2015-06-13 22:33:01

标签: java xml multithreading

我正在尝试读取具有多个线程的XML文档。文件非常大!如果我使用sinlge线程该程序,但如果我使用工作线程,我会得到错误。 作为单个线程,加载大约需要30-40秒。作为多线程,它需要大约5秒钟。所以优势很明显。但是我无法让它发挥作用。 如果有人能够对此有所了解,我很想知道。

这是一些代码。不完全是我的东西(删除了很​​多评论和try-catch块以及与问题无关的东西)

        import org.w3c.dom.*;
        import java.net.URL;
        private static DocumentBuilder getBuilder() {
          try {
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            return dbFactory.newDocumentBuilder();
          } catch (ParserConfigurationException ex) {
            String err = "error initializing API interface: \n" + ex.getMessage();
            System.out.println(err);
            JOptionPane.showMessageDialog(null, err, "Loading error", JOptionPane.WARNING_MESSAGE);
            System.exit(1);
          }
          return null;
        }
        public void loadPage(String page) {
          URL url = new URL(page);
          Document doc = getBuilder().parse(url.openStream());
          Element root = doc.getDocumentElement();
          NodeList nodes = root.getChildNodes();
          for (int i = 0; i < nodes.getLength(); i++) {
            Node n = nodes.item(i);
            if (n instanceof Element) {
              // move node to new document.
              Document doc;
              doc = getBuilder().newDocument();
              Node nn = doc.adoptNode(n);
              doc.appendChild(nn);
              Element ele = (Element)nn;
              new Parser(ele).start(); // Causes errors...
              //new Parser(ele).run(); // Works, but isn't threaded.
              NodeList nodes = root.getChildNodes();
              i = 0;
            }
          }
        }
        public class Parser implements Runnable {
          private Element ele;
          public Parser(Element e) {
            ele = e;
          }
          public void start() {
            new Thread(this).start();
          }
          @Override
          public void run() {
            // Parse the document here.
            // I get errors here if it's multi-threaded.
          }
        }

编辑:

错误是数据损坏。经过进一步测试,我发现问题比我想象的还要糟糕。上面的函数'loadPage'是从一个线程调用的。我发布这个问题时的测试是在只运行一个线程的情况下完成的。但是我发现如果我在parrelell中运行多个页面加载(即使认为它们是完全不同的页面),即使我每页只使用一个线程,我也会收到错误...

我担心会在某个地方使用静态对象导致状态损坏并导致数据损坏。

损坏数据的一个例子是这样的。

     // when reading the XML
     // <Date>2015-6-1</Date>
      public String getText(Element ele) {
        String val = ele.getFirstChild().getNodeValue();
      }
     // I will get either an empty string or somthing like "13E13" or ".5D4"

通过多页加载,我的意思是:

        public void loadAll(List<String> pages) {
          for(String page : pages) {
            new Loader(page).start();
          }
        }
        public class Loader implements Runnable {
          private String page;
          public Loader(String p) {
            page = p;
          }
          public void start() {
            new Thread(this).start();
          }
          @Override
          public void run() {
            loadPage(page);
          }
        }

1 个答案:

答案 0 :(得分:0)

DOM不是线程安全的。所有访问都需要同步,甚至是只读访问。这是因为DOM进行了懒惰评估,因此明显的读取请求可以触发内部更新。一切都非常可怕。如果可能的话,使用XOM或JDOM2会好得多。