国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

一個生產(chǎn)-消費(fèi)模式的XML解析實現(xiàn)

2019-11-18 12:49:43
字體:
供稿:網(wǎng)友

  在B2B(企業(yè)對企業(yè))應(yīng)用中xml扮演一個重要的角色。在這些應(yīng)用中采用Simple API for XML (SAX)或者document.nbspObject Model (DOM)解析器來解析xml文件。(這兩個解析器都是java的api,他們可以在下面的附錄中找到)在一個單線程應(yīng)用中解析是簡單明了的。但是,在多線程的應(yīng)用中這就是很復(fù)雜和具有挑戰(zhàn)性了,比如說做一個應(yīng)用服務(wù)器,因為應(yīng)用經(jīng)常會為解析xml創(chuàng)建一個專門的線程,解析的數(shù)據(jù)用來為許多同時并發(fā)運(yùn)行的線程服務(wù)。這篇文章描述了一個在并發(fā)應(yīng)用中的xml的解析實現(xiàn)。
  
  設(shè)計方法
  基于并發(fā)的生產(chǎn)和消費(fèi)設(shè)計概念,一個專門的線程作為一個生產(chǎn)者去解析xml。一組線程作為消費(fèi)者,作為解析xml數(shù)據(jù)的生產(chǎn)線程,他把數(shù)據(jù)存儲在一個共享的數(shù)據(jù)結(jié)構(gòu)中以供消費(fèi)線程在將來進(jìn)行處理時取得,為了最大化產(chǎn)生數(shù)據(jù)的能力同時最小化內(nèi)存的使用,這個設(shè)計使用了一個非凡的隊列來分別為生產(chǎn)者、消費(fèi)者存儲和找到解析的數(shù)據(jù).
  
  巧妙的隊列(Smart Queuing)
  SmartQueue 隊列類提供給生產(chǎn)消費(fèi)線程們隊列的功能,他主要的責(zé)任是維護(hù)隊列防止(線程)超載和斷流。換句話說,SmartQueue采用維護(hù)一個固定長度的隊列的方法去保持資源的應(yīng)用效率。他掛起和喚醒適當(dāng)?shù)木€程在適當(dāng)?shù)臅r候,打個比方,假如沒有填充數(shù)據(jù)的空間,隊列將掛起生產(chǎn)線程直到一個消費(fèi)線程從隊列里移去一項。
  
  下面的SmartQueue 代碼片斷展示了這種策略的實現(xiàn)。
  public synchronized void put(Object data) {
    // check to see if the length is 2
    while (list.size() >= 2) {
      try {
        System.out.        wait();
      }
      catch (Exception ex) {
      }
    }
  
    list.add(data);
    notifyAll();
  }
  
  public synchronized Object take() {
    // wait until there is data to get
    // come out if the end of file signaled
    while (list.size() <= 0 && (eof != true)) {
      try {
        System.out.println("Waiting to consume data");
        wait();
      } catch (Exception ex) {
      }
    }
  
    Object obj = null;
  
    if (list.size() > 0) {
      obj = list.remove(0);
    } else {
      System.out.println("Woke up because end of document.quot;);
    }
  
    notifyAll();
    return obj;
  }
  
  xml 解析
  這個設(shè)計使用SAX API來解析XML文件是有以下原因的:
  這個API讀取 XML數(shù)據(jù)是快速高效的,他不構(gòu)造任何內(nèi)部的XML數(shù)據(jù)描述,相應(yīng)的,他在碰到XML元素時簡單的把數(shù)據(jù)傳遞給應(yīng)用程序。SAX API十分適合生產(chǎn)-消費(fèi)模式.
  xml 解析控制器(XMLParserHandler) 的類繼續(xù)自SAX,實現(xiàn)回叫(callback )方法從解析器中接收XML數(shù)據(jù),當(dāng)解析控制器類從解析器中接收XML數(shù)據(jù)時,他把數(shù)據(jù)put進(jìn)hashtable里。在每個文檔的結(jié)尾,解析控制器把數(shù)據(jù)put進(jìn)SmartQueue隊列里。這個控制器將進(jìn)入一個等待狀態(tài)假如SmartQueue隊列里有空間,一旦消費(fèi)線程從SmartQueue隊列中移去一項,put方法將被調(diào)用。在完成整個XML文檔的解析后,解析控制器(
  XMLParserHandler)通知消費(fèi)線程停止搜索更多的文檔。
  
  讓我們看看回叫(callback )方法,他把數(shù)據(jù)存儲入SmartQueue隊列然后通知等待的消費(fèi)線程。起始元素(startElement)方法為每個XML文件中的每個文擋元素示例一個新的Hashtable。
  public void startElement( String namespaceURI, String localName,
  String qName, Attributes atts )
    throws SAXException {
    System.out.println(
      " startElement local names............." +
      localName + " " + qName);
      if (qName.equalsIgnoreCase(elemmark)) {
        doc = new Hashtable();
      }
    elem = qName;
  }
  
  結(jié)尾元素(endElement)方法負(fù)責(zé)把解析的數(shù)據(jù)加到SmartQueue隊列中。就象前面提起的,SmartQueue隊列掛起這個線程直到?jīng)]有空間來存儲數(shù)據(jù)。
  public void endElement( String namespaceURI, String localName,
  String qName )
    throws SAXException {
    String s = sbData.toString();
  
    System.out.println("element " + elem + " character " + s);
  
    if ((doc != null) & (s != null) & !(s.trim().equals("")))
      doc.put(elem, s);
  
    sbData = new StringBuffer();
    System.out.println(" endElement ending element............." + qName);
  
    if (qName.equalsIgnoreCase(elemmark)) {
      System.out.println(
        " endElement ending element............." + localName);
  
      smartQueue.put(doc);
      doc = null;
    }
  }
  
  最終,結(jié)尾文檔元素(enddocument.nbsp)回叫方法通知消費(fèi)線程到達(dá)了xml文檔的結(jié)尾。這意味著消費(fèi)線程不用去等待其他數(shù)據(jù)完成他們的工作。
  public void enddocument.) throws SAXException {
    smartQueue.end();
    System.out.println("End document.............");
  }
  
  消費(fèi)線程
  消費(fèi)線程移從SmartQueue隊列中除項目一旦生產(chǎn)線程把項目放入SmartQueue隊列。假如SmartQueue隊列為空,每個消費(fèi)線程將要進(jìn)入等待狀態(tài)。消費(fèi)線程會一直運(yùn)行直到生產(chǎn)線程通知已經(jīng)達(dá)到了文檔元素的結(jié)尾而且SmartQueue隊列中再沒有項目了。這里有一個消費(fèi)線程的例子實現(xiàn),他保持不斷地從SmartQueue隊列中取數(shù)據(jù)直到隊列中沒有數(shù)據(jù)或者達(dá)到了文檔元素的末尾。
  public void run() {
    while (!queue.isEmpty() !queue.onEnd()) {
      Hashtable val = (Hashtable) queue.take();
  
      System.out.println("OBTained by " + this.getName() + " " + val);
  
      // try {
      //   System.out.println("Simulate lengthy
  processing...........");
      //   Thread.sleep(2000);
      // }
      // catch(Exception ex){}
    }
  }
  
  優(yōu)點(diǎn)
  這個設(shè)計有以下優(yōu)點(diǎn):
  解析和數(shù)據(jù)消費(fèi)可以并發(fā)的進(jìn)行。大的xml文件只用很少的內(nèi)存就能被解析
  
  設(shè)計的擴(kuò)展
  SmartQueue隊列執(zhí)行固定長度隊列的策略來維護(hù)內(nèi)存的效率。改變它的T取(take)和存(put)方法,你能執(zhí)行一個不同的策略。在前面提到的,xml解析控制器(XMLParserHandler)產(chǎn)生一個xml元素和值的hashtable。然而,這個類可以被定制去建立應(yīng)用指定的對象。
  
  例子程序
  source.z
ip文件包括一個TestProdUCerConsumerForXML類可以把xml文件作為一個參數(shù)運(yùn)行。根據(jù)下面的說明來運(yùn)行程序,
  Unzip the source.zip file.
  Run the program TestProducerConsumerForXML with order.xml.
  For example
  
  c:/testarea>java -classpath c:/testarea prodcons.TestProducerConsumerForXML c:/testarea/prodcons/order.xml
  這篇文章用一些程序描述了解析xml文檔元素的方法,也解釋了一些關(guān)于生產(chǎn)和消費(fèi)模式的概念,還有和線程的應(yīng)用。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 开封县| 中阳县| 新龙县| 海伦市| 文化| 花垣县| 临西县| 裕民县| 新巴尔虎右旗| 德安县| 禹城市| 吉安县| 宝坻区| 名山县| 肥城市| 绥芬河市| 榆树市| 凭祥市| 丰台区| 三门县| 淮阳县| 噶尔县| 临洮县| 桃江县| 西安市| 临夏市| 望城县| 景洪市| 台江县| 晋宁县| 沅江市| 广宗县| 博乐市| 乌苏市| 新建县| 宜都市| 延寿县| 新建县| 丰宁| 乃东县| 郴州市|