分享
 
 
 

一个生产-消费模式的XML解析实现

王朝other·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

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

设计方法

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

巧妙的队列(Smart Queuing)

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

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

public synchronized void put(Object data) {

// check to see if the length is 2

while (list.size() = 2) {

try {

System.out.println("Waiting to put data");

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

解析

这个设计使用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 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;

}

结尾元素(endElement)方法负责把解析的数据加到SmartQueue队列中。就象前面提起的,SmartQueue队列挂起这个线程直到没有空间来存储数据。

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;

}

}

最终,结尾文档元素(enddocument.nbsp)回叫方法通知消费线程到达了xml文档的结尾。这意味着消费线程不用去等待其他数据完成他们的工作。

public void enddocument.) throws SAXException {

smartQueue.end();

System.out.println("End document.............");

}

消费线程

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

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){}

}

}

优点

这个设计有以下优点:

解析和数据消费可以并发的进行。大的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:\testareajava -classpath c:\testarea prodcons.TestProducerConsumerForXML c:\testarea\prodcons\order.xml

这篇文章用一些程序描述了解析xml文档元素的方法,也解释了一些关于生产和消费模式的概念,还有和线程的应用。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有