【问题标题】:Multithreading - SaxParser Parsing multiple xml files parallaley多线程 - SaxParser 并行解析多个 xml 文件
【发布时间】:2017-11-30 17:23:14
【问题描述】:

目标 - 使用 sax 解析器并行解析不同的 xml 文件 多个线程。

找到多个与同一主题相关的帖子。但他们都没有指出答案。

Question 1Question 2

我知道 SAXParserFactory 和 SAXParser 不是线程安全的。根据我的研究,我需要为每个线程创建 SAXParserFactory 和 SAXParser 的新实例。 我怎样才能做到这一点。 (也是 MySAXHandler 的新实例)

请找到我的代码的当前实现。

SAXParser 的启动

@Override
public GameStatisticsDTO processStatsGameStatXML(File gameStatsStatFile) {
    try(InputStream inputStream = new FileInputStream(gameStatsStatFile)) {
        // New Handler instance
        GameStatsSAXHandler gameStatsSAXHandler = new GameStatsSAXHandler();

        Reader reader = new InputStreamReader(inputStream, Constants.ENCODING_TYPE_UTF_8);
        InputSource inputSource = new InputSource(reader);
        inputSource.setEncoding(Constants.ENCODING_TYPE_UTF_8);

        // New Instance of SAXParserFactory
        SAXParserFactory factory = SAXParserFactory.newInstance();
        factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);

        // New Instance of SAXParser
        SAXParser saxParser = factory.newSAXParser();

        // Create an XML reader to set the entity resolver.
        XMLReader xmlReader = saxParser.getXMLReader();
        xmlReader.setEntityResolver(new StatsCustomResolver());
        xmlReader.setContentHandler(gameStatsSAXHandler);
        xmlReader.parse(inputSource);
        return gameStatsSAXHandler.getGameStatisticsDTO();
    } catch (Exception e) {
        throw new UnprocessableEntityException();
    }
}

这将调用 GameStatsSAXHandler 来解析 xml 节点。 Within that class I'm maintaining Instance reference variables to store my parsed data.

public class GameStatsSAXHandler extends DefaultHandler {

   // Instance Reference Variable - Hope this is thread safe
   private GameStatisticsDTO gameStatisticsDTO = new GameStatisticsDTO();

   protected GameStatisticsDTO getGameStatisticsDTO() {
      return this.gameStatisticsDTO;
   }

   @Override
   public void startElement (String uri, String localName, String 
     elementName, Attributes attributes) throws SAXException {
        // Process the data and add it to the gameStatisticsDTO
   }

   @Override
   public void endElement (String uri, String localName, String 
      elementName) throws SAXException {
        // Do some processing in gameStatisticsDTO
   }
}

gameStatisticsDTO 包含多个实例引用变量(对象和列表)

所以我有 2 个问题。

1) 因为只有局部原始变量是线程安全的。这是 GameStatsSAXHandler 及其 GameStatisticsDTO 是线程安全的?

我的想法:如果我为每个线程创建新的 GameStatsSAXHandler 实例,那么 GameStatisticsDTO 将是线程安全的。

2) 如何将其转换为多线程环境 并行性。

我的想法:创建 ThreadPoolExecutor 并传递新的 SAXParserFactory 并生成新的 SAXParser 并创建新的 GameStatsSAXHandler 并将其传递给基方法进行处理。 (processStatsGameStatXML 方法)

但是我怎样才能为每个线程创建新的实例呢?代码示例会很棒! 谢谢

【问题讨论】:

  • 首先需要多线程吗? SAX 也是正确的解析模型吗?

标签: java xml multithreading parallel-processing saxparser


【解决方案1】:

您将任务提交给ThreadPoolExecutor。任务通常是您保留与特定任务相关的所有上下文(即状态)数据的位置,在您的情况下,是一个文件的解析。

所以是这样的:

class ParsingTask implements Runnable {
    private SAXParserFactory factory;
    private SAXParser parser;
    private GameStatsHandler handler;
    // whatever else needed for parsing

    @Override
    public void run() {
        // actual parsing code
    }
}

[Edit] 附带说明,我认为SAXParserFactory 的实现通常是线程安全的。除非您需要在不同的解析任务之间对工厂进行不同的配置,否则可能不需要每次在每个新的解析任务上都实例化它。

【讨论】:

  • @jingx感谢您的回复。但是 SAXParseFactory 不是线程安全的。 oracle impl。所以我必须为每个线程创建一个实例。我知道它有点贵。
  • 那是不是 Oracle 对SAXParserFactory 的实现,而是接口本身。另请注意,您引用的是 JDK 1.5,从 JDK 8 开始,关于线程安全的部分已被删除。你想从你使用的包中找到实现类,并阅读它的文档来决定它是否是线程安全的。
  • 是的,我的错。我指的是 1.5 文档。感谢您指出。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-08
  • 1970-01-01
  • 2018-01-30
  • 2020-01-09
  • 2014-12-22
相关资源
最近更新 更多