我正在尝试读取具有多个线程的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);
}
}
答案 0 :(得分:0)
DOM不是线程安全的。所有访问都需要同步,甚至是只读访问。这是因为DOM进行了懒惰评估,因此明显的读取请求可以触发内部更新。一切都非常可怕。如果可能的话,使用XOM或JDOM2会好得多。