XML Parsing in a Producer-Consumer Model
mem_fox 翻译  (参与分:425,专家分:410)   发表:2003-11-10 下午11:16   版本:1.0   阅读:1520

  显示XML数据是集成B2B应用程序的重要角色。一般应用程序可以实用SAX或者DOM的方式解析XML文件。在单线程的环境下解析XML的程序是非常简单的,但在多线程的模式下,这项工作就会变得相当的复杂。比如在应用服务器一般会创建一个专用的线程去解析XML数据,并将解析数据提供给一个或多个其他线程使用。现在我们开始实现这样的XML解析程序.

Design Approach(设计实现)

按照producer-consumer的程序设计思想,需要一个专门的线程来扮演生成者去解析XML数据,而另外的一个线程组则充当消费者的角色。生成者在解析XML数据的同时保存结果一个共享的数据结构中,以供消费者来获取当前的处理结果。这个设计使用一个特殊的队列让生成者和消费者可以分别保持和获取解析的结果,以达到最大的吞吐量和最小的内存消耗。

Smart Queuing

SmartQueue类为producer-consumer线程组提供队列服务。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");
    }

notifyAll();
    return obj;
}

XML Parsing

为什么使用SAX的方式来解析XML数据
      不创建任何的内部XML数据描述,而只是在遇见元素是简单的将数据发送到应用程序
    随最快和最高效的读取XML数据的方法
    API很时候producerconsumer模型
  XMLParserHandler类继承SAX,实现了通过方法回调的方式获取解析的XML数据。当XMLParserHandler将从Parser中获取的数据保存到Hahstablezhong。当到Element的结尾处时,则将Hashtable对象put进SmartQueue队列。当SmartQueue没有空闲位置时,Handler则进入等待状态直到消费线程移除数据后,put方法才可以完成。当XML文档完全解析后,XMLParseHandler会通知消费线程停止寻找更多的数据。
 让我们着眼于如何用回调的方法向SmartQueue中保存数据并唤醒等待的消费者线程。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方法中则负责将解析的XML数据添到SmartQueue队列中。就象上面提到的,SmartQueue队列hold当前的线程到有空闲空间存储数据。
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的回调方法中通知所有的消费者线程文档解析结束。这意味这所有的消费者线程在其结束自己工作之前,不再需要等待更多的数据
public void endDocument() throws SAXException {
    smartQueue.end();
    System.out.println("End Document.............");
}

Consumer Threads

消费者线程从SmartQueue队列中读取生产者线程存储的数据。当SmartQueu队列中没有数据是,所有的消费者线程都进入等待状态。当生产者线程发出文档解析结束的信号和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){}
    }
}

Benefits

这个设计有以下的优点
  解析数据和使用数据可以并行处理
  可以用较小的内存使用量,解析大的XML文件

Extending the Design

现在的SmartQueue是在定长的策略下有效的管理内存数据,我们可以定义不同的策略实现Take和Put方法。就象上面提到的,可以建立专用的对象来代替Hashtable来保存XMLParserHandler解析的XML元素和值。

PS 我知道我翻译的水平很烂,希望大家可以指正。只是感觉这篇文章和设计模式结合的很好介绍给大家,如果有任何评论欢迎到 用代码说话,那个是我的新blog

转载于:https://www.cnblogs.com/sunsonbaby/archive/2004/09/10/41947.html

XML Parsing in a Producer-Consumer Model相关推荐

  1. .net IO异步和Producer/Consumer队列实现一分钟n次http请求

    简介 最近工作中有一个需求:要求发送http请求到某站点获取相应的数据,但对方网站限制了请求的次数:一分钟最多200次请求. 搜索之后,在stackoverflow网站查到一个类似的问题..但里面用到 ...

  2. XML Parsing Error: mismatched tag. Expected

    用Firefox不愧为技术呆子,哪怕是一个HTML标签部规范,都会给出ERROR MESSAGE. Long long ago 习惯用IE开发,自从chrome诞生后,慢慢chrome赶走了IE,偶尔 ...

  3. Producer Consumer

    需要与Eureka结合使用 Eureka环境搭建 Producer 一.pom文件 <?xml version="1.0" encoding="UTF-8" ...

  4. Kafka入门教程其一 消息队列基本概念 及常用Producer Consumer配置详解学习笔记

    文章目录 1. 综述 2. 消息队列(Message Queue) 2.1 点对点 2.2 发布/订阅(pub-sub) 3. Kafka基础术语解释 3.1 Broker 3.2 Partition ...

  5. java多线程并发之旅-09-java 生产者消费者 Producer/Consumer 模式

    生产者消费者模式 在实际的软件开发过程中,经常会碰到如下场景:某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类.函数.线程.进程等).产生数据的模块,就形象地称为生产 ...

  6. 你说五毛就五毛? 生产者消费者模式(Producer Consumer Pattern)来讲解

    目的 效率型设计模式, 意义在于不阻塞主流程的同时完成异步操作, 比如发邮件短信, 完成耗时的任务等 例子代码 最近蜂巢收费 5 毛的事件引起了业主和物业的强烈反对, 5 毛钱其实也不是很多, 掉地上 ...

  7. 浅议NetMQ常见模式和消息加密机制

    题图来自https://www.pexels.com/ 概述 在传统企业级开发中,消息队列机制已经成为一种非常常见的技术实现手段,而基于NetMQ则看起来有点像一朵"奇葩",看起来 ...

  8. Oracle 19c VLDB and Partitioning Guide 第8章:Using Parallel Execution 读书笔记

    本文为Oracle 19c VLDB and Partitioning Guide第8章Using Parallel Execution的读书笔记. 并行执行是通过使用多个进程将多个 CPU 和 I/ ...

  9. DeviceNet技术及其产品开发

    DeviceNet技术及其产品开发 2008-2-28 10:53:00 来源:作者: 网友评论 0条 点击查看 <script src="http://www.ca800.com/a ...

最新文章

  1. 智能车竞赛技术报告 | 专科基础组 - 哈尔滨铁道职业技术学院 - 智能车勇创协会
  2. 一个 MVC 框架以 MVVM 之「魂」复活了!
  3. OpenDDS安装与开发
  4. julia 调用python库_Julia调用Python实现超像素分割SLIC算法
  5. 安德鲁斯Selector简介
  6. python从excel中读取数据
  7. 【C++基础学习】关于C++静态数据成员
  8. java调用jndi出错,Webshpere数据源错误:无法查找JNDI名称
  9. 《以截屏为基础的演示文档制作软件》(ScreenSteps Pro)更新v2.9.1/含注册机[压缩包]...
  10. 新学到的Url形成方法
  11. js ajax提交数据php,js中ajax提交到php的json数据,php无法获得
  12. 网络通信基础(入门知识总结)
  13. ftp客户端软件,Windows端有哪些ftp客户端软件值得推荐?3款ftp客户端软件
  14. tmux使用指南:1 :简介与安装
  15. 百度地图api 在3D地图中设置自定义样式
  16. 数组的缩减(简易版)
  17. 国产32层堆栈3D闪存2019年量产 2020年赶超国际
  18. IDEMIA任命Astrid Warren为首席人力官
  19. Web前端:实现在一块区域(div)点击链接,在同一页面的指定区域显示链接的内容——基于css与div结合网页布局设计
  20. 基于声音的击键信号识别

热门文章

  1. c语言大作业菜单,C语言大作业:编写菜单控制猜商品价格程序
  2. mysql stop很久_mysql的timeout
  3. iphone照片删掉又出现_两个月前删的IPhone手机照片还有救?很简单,三招帮你轻松恢复...
  4. mysql 同步更新_MySQL slave 不能同步更新
  5. watch深度监听数组_vue watch普通监听和深度监听实例详解(数组和对象)
  6. python爬_python爬虫--模拟登录知乎
  7. 网络安全-防火墙与入侵检测系统
  8. Mysql字符集之utf8和utf8mb4的使用问题
  9. docker安装配置分布式elasticsearch、kibana、head、cerebro
  10. Linux Shell脚本编程--grep命令