2009-09-07 40 views
0

我編寫了一個多線程程序,每個線程都需要解析一個xml文件並更新新的值。問題:假設我有一個xml內容的ABC,現在線程A解析xml並更新它成爲ABCA,同時線程B也解析xml(內容是ABC)並更新它成爲ABCB。線程B在線程A更新後更新xml,所以xml的結果是ABCB,我想要的是xml結果應該是ABCAB。任何想法來控制線程中解析和更新的方式? 這裏是我的代碼:Java解析並更新線程中的xml值

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(); 
    } 

回答

1

你需要確保只有一個線程在任何時間訪問文件。您可以使用可用的本地同步工具(如​​關鍵字和wait()/notify()機制),也可以查看更高級別的同步工具,例如SemaphoreFileLock

+0

謝謝。我的程序現在使用同步工作 – winsontan520 2009-09-08 10:37:07

1

當你同步一個方法時,對對象(對於非靜態方法)進行鎖定,因爲每個線程都有自己的WebServicesXML實例,每個實例都可以獲得鎖定並且不會發生阻塞。

解決這個問題的最簡單方法是隻創建WebServicesXML的單個實例,並在創建時將該單個實例傳遞給每個線程。

WebServicesXML可選地創建信號對象是這樣的:

private static final Object FILE_SEMAPHORE = new Object(); 

,然後添加一個同步塊一輪更新這樣的文件中的行:

synchronized (FILE_SEMAPHORE) { 

    //File update code goes here. 

} 
2

的基本問題是一個單獨的每個線程都內置DOM,以便應用單個轉換。這意味着要將其內容寫回到XML文件,最後一個要運行的線程'獲勝'。

一方面,您使用線程,我假設性能,但另一方面,您多次解析和序列化XML。線程實現是不安全的。

我的建議是刪除線程並在循環中進行更改。當它工作時,您可以衡量性能,然後選擇使用線程查看實現。請記住,不成熟的優化是一切罪惡的根源。

+0

感謝您的回覆。爲了消除線程聲音問題,我的程序需要執行子進程的動態編號並監視子進程。任何想法都會過來呢? – winsontan520 2009-09-08 09:51:40

+0

您有多個子進程可能需要修改文件系統上的相同XML文件?在這種情況下,使用鎖定文件模式來同步對文件的訪問。 – SteveD 2009-09-08 21:42:08