xml解析:生产-消费模式的XML解析

  在B2B(企业对企业)应用中XML扮演个重要角色在这些应用中采用Simple API for XML (SAX)或者document.nbspObject Model (DOM)解析器来解析xml文件(这两个解析器都是javaapi他们可以在下面附录中找到)在个单线程应用中解析是简单明了但是在多线程应用中这就是很复杂和具有挑战性了比如说做个应用服务器应用经常会为解析xml创建个专门线程解析数据用来为许多同时并发运行线程服务这篇文章描述了个在并发应用中xml解析实现

  设计思路方法

  基于并发生产和消费设计概念个专门线程作为个生产者去解析xml组线程作为消费者作为解析xml数据生产线程他把数据存储在个共享数据结构中以供消费线程在将来进行处理时取得为了最大化产生数据能力同时最小化内存使用这个设计使用了个特别队列来分别为生产者、消费者存储和找到解析数据.

  巧妙队列(Smart Queuing)

  SmartQueue 队列类提供给生产消费线程们队列功能他主要责任是维护队列防止(线程)超载和断流换句话说SmartQueue采用维护个固定长度队列思路方法去保持资源应用效率他挂起和唤醒适当线程在适当时候打个比方如果没有填充数据空间队列将挂起生产线程直到个消费线程从队列里移去

  下面SmartQueue 代码片断展示了这种策略实现

public synchronized void put(Object data) {
// check to see the length is 2
while (list.size >= 2) {
try {
.out.prln("Waiting to put data");
wait;
}
catch (Exception ex) {
}
}
list.add(data);
notyAll;
}
public synchronized Object take {
// wait until there is data to get
// come out the end of file signaled
while (list.size <= 0 && (eof != true)) {
try {
.out.prln("Waiting to consume data");
wait;
} catch (Exception ex) {
}
}
Object obj = null;
(list.size > 0) {
obj = list.remove(0);
} {
.out.prln("Woke up because end of document.quot;);
}
notyAll;
obj;
}
  xml 解析

  这个设计使用SAX API来解析XML文件是有以下原因:

  这个API读取 XML数据是快速高效,他不构造任何内部XML数据描述相应他在遇到XML元素时简单把数据传递给应用SAX API十分适合生产-消费模式

  xml 解析控制器(XMLParserHandler) 类继承自SAX实现回叫(callback )思路方法从解析器中接收XML数据当解析控制器类从解析器中接收XML数据时他把数据put进hashtable里在每个文档结尾解析控制器把数据put进SmartQueue队列里这个控制器将进入个等待状态如果SmartQueue队列里有空间旦消费线程从SmartQueue队列中移去put思路方法将被在完成整个XML文档解析后解析控制器(

  XMLParserHandler)通知消费线程停止搜索更多文档

  让我们看看回叫(callback )思路方法他把数据存储入SmartQueue队列然后通知等待消费线程起始元素(startElement)思路方法为每个XML文件中每个文挡元素举例个新Hashtable

public void startElement( String URI, String localName,
String qName, Attributes atts )
throws SAXException {
.out.prln(
" startElement local names............." +
localName + " " + qName);
(qName.equalsIgnoreCase(elemmark)) {
doc = Hashtable;
}
elem = qName;
}
  结尾元素(endElement)思路方法负责把解析数据加到SmartQueue队列中就象前面提起SmartQueue队列挂起这个线程直到没有空间来存储数据

public void endElement( String URI, String localName,String qName )
throws SAXException {
String s = sbData.toString;
(qName.equalsIgnoreCase(elemmark)) {
.out.prln(
" endElement ending element............." + localName);
smartQueue.put(doc);
doc = null;
}
}
  最终结尾文档元素(enddocument.nbsp)回叫思路方法通知消费线程到达了xml文档结尾这意味着消费线程不用去等待其他数据完成他们工作

public void enddocument.) throws SAXException {
smartQueue.end;
.out.prln("End document.............");
}
  消费线程

  消费线程移从SmartQueue队列中除项目旦生产线程把项目放入SmartQueue队列如果SmartQueue队列为空每个消费线程将要进入等待状态消费线程会直运行直到生产线程通知已经达到了文档元素结尾而且SmartQueue队列中再没有项目了这里有个消费线程例子实现他保持不断地从SmartQueue队列中取数据直到队列中没有数据或者达到了文档元素末尾

public void run {
while (!queue.isEmpty || !queue.onEnd) {
Hashtable val = (Hashtable) queue.take;
.out.prln("Obtained by " + this.getName + " " + val);
// try {
// .out.prln("Simulate lengthy
processing...........");
// Thread.sleep(2000);
// }
// catch(Exception ex){}
}
}
  优点

  这个设计有以下优点:

  解析和数据消费可以并发进行xml文件只用很少内存就能被解析

  设计扩展

  SmartQueue队列执行固定长度队列策略来维护内存效率改变它T取(take)和存(put)思路方法你能执行个区别策略在前面提到xml解析控制器(XMLParserHandler)产生个xml元素和值hashtable然而这个类可以被定制去建立应用指定对象

  例子

  source.zip文件包括个TestProducerConsumerForXML类可以把xml文件作为个参数运行根据下面介绍说明来运行:



Unzip the source.zip file.
Run the program TestProducerConsumerForXML with order.xml.
For example
c:  estarea>java -path
c:  estarea prodcons.TestProducerConsumerForXML
c:  estareaprodconsorder.xml
  这篇文章用描述了解析xml文档元素思路方法也解释了些有关生产和消费模式概念还有和线程应用



Tags:  java解析xml文件 java解析xml xml解析器 xml解析

延伸阅读

最新评论

发表评论