【问题标题】:Java parse and update xml value in threadJava在线程中解析和更新xml值
【发布时间】:2009-09-07 11:10:22
【问题描述】:

我写了一个多线程程序,每个线程都需要解析一个xml文件并更新新值。问题:假设我有一个ABC的xml内容,现在线程A解析xml并将其更新为ABCA,同时线程B也解析xml(内容为ABC)并将其更新为ABCB。线程B在线程A更新后更新xml,所以xml的结果是ABCB,我想要的是xml结果应该是ABCAB。有什么想法可以控制线程中的解析和更新方式吗? 这是我的代码:

WSthread.java

public class WSthread extends Thread {
    public String WSname;
    Process proc= null;
    WebServicesXML xml;
    WSthread(String name){
        WSname=name;
    }

    public void run() {
try {
    //my code
    // Run a java app in a separate system process
    String cmd = (WSname);
    proc = Runtime.getRuntime().exec("java -jar "+cmd);
    xml = new WebServicesXML();
    //Process proc = Runtime.getRuntime().exec("java -jar .jar");
    // Then retreive the process output
    //InputStream in = proc.getInputStream();
    //InputStream err = proc.getErrorStream();

    BufferedReader is = new BufferedReader(new InputStreamReader(proc.getInputStream()));
    String line;
    String regex = "\\bhttp\\b";
    Pattern pattern = Pattern.compile(regex);
    String WSaddress = "";
    while ((line = is.readLine()) != null){
        Matcher matcher = pattern.matcher(line);
        if(matcher.find()){
            WSaddress = line;
            System.out.println("Updating WS address..."+WSaddress);
            xml.create(WSname, WSaddress);
        }
        System.out.println(line);
    }

    }catch(Exception e){
        System.out.println(e.getMessage());
    }
}
    public void close(){
        proc.destroy();
    }

WebServicesXML.java

public class WebServicesXML{
public int totalWebServices;
public String WSnamelist[];
public synchronized void create(String WSname, String WSaddress) throws OException,     TransformerConfigurationException, TransformerException, ParserConfigurationException{
    try {

    DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
    DocumentBuilder docBuilder = dbfac.newDocumentBuilder();

    Document readdoc = docBuilder.parse("webservices.xml");
//      normalize text representation
    readdoc.getDocumentElement ().normalize ();
    Node rootList = readdoc.getDocumentElement();
    Element rootElement = (Element)rootList;

    Element webservice = readdoc.createElement("WebService");

    Element name = readdoc.createElement("name");
    Element address = readdoc.createElement("address");

    name.setTextContent(WSname);
    address.setTextContent(WSaddress);

    webservice.appendChild(name);
    webservice.appendChild(address);

    rootElement.appendChild(webservice);
    /////////////////
    //Output the XML

    //set up a transformer
    TransformerFactory transfac = TransformerFactory.newInstance();
    Transformer trans = transfac.newTransformer();
    trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
    trans.setOutputProperty(OutputKeys.INDENT, "yes");

    //create string from xml tree
    File file = new File("webservices.xml");
    StringWriter sw = new StringWriter();
    StreamResult result = new StreamResult(file);
    DOMSource source = new DOMSource(readdoc);
    trans.transform(source, result);

}
    catch (ParserConfigurationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (SAXException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (TransformerConfigurationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (TransformerException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

【问题讨论】:

    标签: java xml


    【解决方案1】:

    基本问题是在每个线程中构建了一个单独的 DOM,以便应用单个转换。这意味着在将其内容写回 XML 文件方面,最后一个运行的线程“获胜”。

    一方面您使用线程,我假设是为了提高性能,但另一方面您会多次解析和序列化 XML。而且线程实现是不安全的。

    我的建议是删除线程并在循环中进行更改。当它工作时,您可以测量性能,然后选择查看使用线程的实现。

    请记住,过早的优化是万恶之源。

    【讨论】:

    • 感谢您的回复。对我来说消除线程声音问题,我的程序需要执行子进程的动态数量并监视子进程。有什么想法可以解决这个问题吗?
    • 您有多个子进程可能需要修改文件系统上的同一个 XML 文件?在这种情况下,请使用锁定文件模式来同步对文件的访问。
    【解决方案2】:

    您需要确保任何时候只有一个线程在访问该文件。您可以使用可用的本机同步工具(例如synchronized 关键字和wait()/notify() 机制),或者您可以查看更高级别的同步工具,例如SemaphoreFileLock

    【讨论】:

      【解决方案3】:

      当您同步一个方法时,会在对象上获取锁(对于非静态方法),因此因为每个线程都有自己的 WebServicesXML 实例,所以每个线程都可以获得一个锁并且不会发生阻塞。

      处理此问题的最简单方法是仅创建 WebServicesXML 的单个实例,并在创建时将该单个实例传递给每个线程。

      或者在WebServicesXML 中创建一个信号量对象,如下所示:

      private static final Object FILE_SEMAPHORE = new Object();
      

      然后在更新文件的行周围添加一个同步块,如下所示:

      synchronized (FILE_SEMAPHORE) {
      
        //File update code goes here.  
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-08-26
        • 1970-01-01
        • 1970-01-01
        • 2019-09-13
        • 1970-01-01
        • 2019-05-08
        • 2011-12-22
        • 2016-10-31
        相关资源
        最近更新 更多