生活随笔
收集整理的這篇文章主要介紹了
XML Parsing in a Producer-Consumer Model
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
| XML?Parsing?in?a?Producer-Consumer?Model | | mem_fox 翻譯? (參與分:425,專家分:410)?? 發(fā)表:2003-11-10 下午11:16 ??版本:1.0 ??閱讀:1520次 |
|
??顯示XML數(shù)據(jù)是集成B2B應(yīng)用程序的重要角色。一般應(yīng)用程序可以實用SAX或者DOM的方式解析XML文件。在單線程的環(huán)境下解析XML的程序是非常簡單的,但在多線程的模式下,這項工作就會變得相當(dāng)?shù)膹?fù)雜。比如在應(yīng)用服務(wù)器一般會創(chuàng)建一個專用的線程去解析XML數(shù)據(jù),并將解析數(shù)據(jù)提供給一個或多個其他線程使用。現(xiàn)在我們開始實現(xiàn)這樣的XML解析程序.
Design?Approach(設(shè)計實現(xiàn)) ??按照producer-consumer的程序設(shè)計思想,需要一個專門的線程來扮演生成者去解析XML數(shù)據(jù),而另外的一個線程組則充當(dāng)消費者的角色。生成者在解析XML數(shù)據(jù)的同時保存結(jié)果一個共享的數(shù)據(jù)結(jié)構(gòu)中,以供消費者來獲取當(dāng)前的處理結(jié)果。這個設(shè)計使用一個特殊的隊列讓生成者和消費者可以分別保持和獲取解析的結(jié)果,以達(dá)到最大的吞吐量和最小的內(nèi)存消耗。
Smart?Queuing ??SmartQueue類為producer-consumer線程組提供隊列服務(wù)。SmartQueue類的主要功能就是管理隊列的長度。換句話說,就是使用固定長度隊列策略有效的維護(hù)資源。通過掛起和喚醒適當(dāng)?shù)木€程以保證隊列的長度。比如當(dāng)需要添加數(shù)據(jù)是,發(fā)現(xiàn)已經(jīng)沒有位置,則掛起生產(chǎn)者線程,直到有消費者線程移除一些數(shù)據(jù)。 下面的代碼片段為策略的實現(xiàn):
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"); ????}
????notifyAll(); ????return?obj; }
XML?Parsing 為什么使用SAX的方式來解析XML數(shù)據(jù) ??????不創(chuàng)建任何的內(nèi)部XML數(shù)據(jù)描述,而只是在遇見元素是簡單的將數(shù)據(jù)發(fā)送到應(yīng)用程序 ????隨最快和最高效的讀取XML數(shù)據(jù)的方法 ????API很時候producerconsumer模型 ??XMLParserHandler類繼承SAX,實現(xiàn)了通過方法回調(diào)的方式獲取解析的XML數(shù)據(jù)。當(dāng)XMLParserHandler將從Parser中獲取的數(shù)據(jù)保存到Hahstablezhong。當(dāng)?shù)紼lement的結(jié)尾處時,則將Hashtable對象put進(jìn)SmartQueue隊列。當(dāng)SmartQueue沒有空閑位置時,Handler則進(jìn)入等待狀態(tài)直到消費線程移除數(shù)據(jù)后,put方法才可以完成。當(dāng)XML文檔完全解析后,XMLParseHandler會通知消費線程停止尋找更多的數(shù)據(jù)。 ?讓我們著眼于如何用回調(diào)的方法向SmartQueue中保存數(shù)據(jù)并喚醒等待的消費者線程。StartElemetn方法為每個Elemetn實例化一個新的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方法中則負(fù)責(zé)將解析的XML數(shù)據(jù)添到SmartQueue隊列中。就象上面提到的,SmartQueue隊列hold當(dā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; ????} }
?最后在endDocument的回調(diào)方法中通知所有的消費者線程文檔解析結(jié)束。這意味這所有的消費者線程在其結(jié)束自己工作之前,不再需要等待更多的數(shù)據(jù) public?void?endDocument()?throws?SAXException?{ ????smartQueue.end(); ????System.out.println("End?Document............."); }
Consumer?Threads 消費者線程從SmartQueue隊列中讀取生產(chǎn)者線程存儲的數(shù)據(jù)。當(dāng)SmartQueu隊列中沒有數(shù)據(jù)是,所有的消費者線程都進(jìn)入等待狀態(tài)。當(dāng)生產(chǎn)者線程發(fā)出文檔解析結(jié)束的信號和SmartQueue隊列中的數(shù)據(jù)為空時,消費線程結(jié)束。下面的代碼就實現(xiàn)的如何讓消費線程在沒有數(shù)據(jù)的時候等待,而在文件解析結(jié)束和SmartQueue中不在有任何數(shù)據(jù)的時候結(jié)束線程運行。 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){} ????} }
Benefits 這個設(shè)計有以下的優(yōu)點 ??解析數(shù)據(jù)和使用數(shù)據(jù)可以并行處理 ??可以用較小的內(nèi)存使用量,解析大的XML文件
Extending?the?Design ?現(xiàn)在的SmartQueue是在定長的策略下有效的管理內(nèi)存數(shù)據(jù),我們可以定義不同的策略實現(xiàn)Take和Put方法。就象上面提到的,可以建立專用的對象來代替Hashtable來保存XMLParserHandler解析的XML元素和值。
PS?我知道我翻譯的水平很爛,希望大家可以指正。只是感覺這篇文章和設(shè)計模式結(jié)合的很好介紹給大家,如果有任何評論歡迎到?用代碼說話,那個是我的新blog
|
|
轉(zhuǎn)載于:https://www.cnblogs.com/sunsonbaby/archive/2004/09/10/41947.html
總結(jié)
以上是生活随笔為你收集整理的XML Parsing in a Producer-Consumer Model的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。