有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java中xml文件的多线程读写

我想用一个线程读取XML文件,并通过两个线程向其添加一些节点。 写入线程不能同时写入文件。读线程读取文件内容并将其放入缓冲区。读卡器执行此操作时,写卡器无法访问此缓冲区

我该怎么做

我通过以下方式读取XML文件并向其中添加节点:

public synchronized void AddNewNode(Document doc) throws TransformerException {

    Element book = doc.createElement("book");
    book.setAttribute("id", "3");

    Element name = doc.createElement("name");
    name.setTextContent("new");
    Element id = doc.createElement("id");
    id.setTextContent("31");
    Element writer = doc.createElement("writer");
    writer.setTextContent("tester");
    Element price = doc.createElement("price");
    price.setTextContent("3100");

    book.appendChild(name);
    book.appendChild(id);
    book.appendChild(writer);
    book.appendChild(price);

    doc.getDocumentElement().appendChild(book);

    TransformerFactory tf = TransformerFactory.newInstance();
    Transformer transformer = tf.newTransformer();
    DOMSource source = new DOMSource(doc);
    StreamResult result = new StreamResult("/home/zahra/workspace/test1/src/xmlfile.xml");
    transformer.transform(source, result);

}
public void ReadNodes(Document doc) {

    NodeList nList = doc.getElementsByTagName("book");
    System.out.println("\n" + ":0 :) :0 :) :0 :) :0 :) :0 :)");
    for (int i = 0; i < nList.getLength(); i++) {

        Node nNode = nList.item(i);
        System.out.println("\n" + "Element number " + (i + 1) + "\n");
        Element eElement = (Element) nNode;
        for (int j = 0; j < eElement.getChildNodes().getLength(); j++) {

            String tagName = eElement.getChildNodes().item(j).getNodeName();
            if (eElement.getElementsByTagName(tagName).getLength() > 0) {
                System.out.println(eElement.getChildNodes().item(j).getNodeName()
                        + " : "
                        + eElement.getElementsByTagName(tagName).item(0).getTextContent());
            }
        }

    }

}

谢谢


共 (1) 个答案

  1. # 1 楼答案

    使用synchronized作为方法修饰符时要非常小心;它通常不会达到你期望的效果。我喜欢将synchronized方法修饰符视为语法糖:

    public void myMethod() {
        synchronized(this) {
            // method body
        }
    }
    

    由于它锁定实例本身,因此它仅限制同一实例在同一时间调用该方法。例如,如果为每个writer创建了一个实例,那么synchronized方法将毫无帮助。在您的情况下,更干净的方法可能是直接在要锁定的对象上进行同步,如:

    public void addNewNode(Document doc) throws TransformerException {
    
        synchronized(doc) {
            Element book = doc.createElement("book");
            book.setAttribute("id", "3");
            // etc, etc.
        }
    }
    

    您可能可以在Reader方法中使用相同的技巧,但是在这种情况下,Reader也会屏蔽这两个编写器。我不太清楚您的用例需要这样的线程和时间安排。即使多线程工作得很好,您仍然会遇到一个问题,即您的读操作是否确实覆盖了每一次写操作(可能存在一种争用情况,即写操作恰好发生在您最近的读操作之前)