【问题标题】:Java read a w3c.Document from different threadJava 从不同的线程读取 w3c.Document
【发布时间】:2015-06-13 22:33:00
【问题描述】:

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

这是一些代码。不完全是我所拥有的(删除了很​​多 cmets 和 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);
          }
        }

【问题讨论】:

  • 您的错误是什么样的?你能发布一个堆栈跟踪吗?
  • 如果您不告诉我们错误是什么,我们将无法帮助您。
  • 找到了问题,在我的代码深处,我有一个正在使用的静态 DateFormat 对象。由于错误字符串中报告的值,我认为数据已损坏。

标签: java xml multithreading


【解决方案1】:

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

【讨论】:

  • 我发现了问题。这与 XML 解析无关,我已将其充分分离为单独的文档。这个问题深埋在我的代码中,是一个被声明为静态并在所有线程之间共享的解析器。这就是破坏我的数据的原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-05
  • 1970-01-01
  • 2017-01-29
  • 2020-02-04
相关资源
最近更新 更多