【问题标题】:Xml parsing and writing txt file using multithread in java在java中使用多线程的xml解析和写入txt文件
【发布时间】:2017-11-03 13:48:04
【问题描述】:

我有很多 xml 文件。每个 xml 文件都包含太多的行和标签。在这里,我必须解析它们并使用 xml 的文件名编写 .txt 文件。这需要快速完成。越快越好。

xml文件示例:

<text>
   <paragraph>
         <line>
             <character>g</character>
             <character>o</character>
                         .....
          </line>
          <line>
             <character>k</character>
                         .....
          </line>
   </paragraph>
</text>
<text>
   <paragraph>
         <line>
             <character>c</character>
                         .....
          </line>
   </paragraph>
</text>

文本文件示例:

go..
k..

c..

如何在 java 中使用多线程尽可能快地解析许多 xml 文件并编写许多文本文件?

我应该从哪里着手解决问题?我用来解析的方法会影响速度吗?如果影响,哪种方法比其他方法更快?

我没有多线程方面的经验。我应该如何构建一个多线程结构才能有效?

感谢任何帮助。提前致谢。

编辑

我需要一些帮助。我使用 SAX 进行解析。我对线程池、多线程、java8 特性做了一些研究。我尝试了一些代码块,但总时间没有变化。如何在我的代码中添加多线程结构或 java8 功能(Lambda 表达式、并行等)?

【问题讨论】:

    标签: java xml multithreading parsing


    【解决方案1】:

    这种情况下的注意事项。

    1. 在许多情况下,尝试使用多线程一次写入多个文件是完全没有意义的。这通常只是过度使用磁盘磁头。
    2. 写入磁盘同时解析也可能是一个瓶颈。您最好将 xml 解析为缓冲区,然后一次性将整个缓冲区写入磁盘。
    3. 解析器的速度不太可能显着影响进程的总时间。与解析相比,您的系统几乎肯定会花费更多更多时间阅读和写作。
    4. 快速检查一些真实的测试数据将是非常宝贵的。尝试准确估计您将无法影响的时间量。
      • 通过将几千个样本文件读入内存来确定近似的总读取时间,因为无论您如何并行处理该过程,仍需要花费该时间。
      • 以类似的方式估计一个近似的总写入时间
      • 将两者相加,并将其与读取、解析和写入这些相同文件的总执行时间进行比较。这应该可以让您很好地了解可以通过并行性节省多少时间。

    并行性并不总是能够解决运行缓慢的进程。您通常可以通过使用适当的硬件显着提高吞吐量。

    【讨论】:

    • (1) 磁盘磁头?磁盘还有磁头吗? (2) 我的测量是读取一个 120Mb 文件(从 SSD)需要 760 毫秒,而解析它需要 1160 毫秒。这不是一个微不足道的区别。
    • 感谢您的评论。首先,在这种情况下使用解析哪个更好? DOM 还是 SAX?我做了研究,但我无法决定。
    • @StefanSatya 我可能会选择像 XOM 这样真正简单的东西,但要准备好改用更好的东西。
    • @MichaelKay 120mb 是一个非常小的样本。尝试几百个演出和几千个文件。
    【解决方案2】:

    首先,您确定需要更快或多线程吗?过早的优化是万恶之源。如果你不小心,你可以很容易地让你的程序变得更复杂以获得不重要的收益,而多线程肯定会让事情变得更复杂。

    但是,对于实际问题: 首先以单线程方式解决这个问题。然后考虑如何将这个问题拆分到多个线程中。 (例如,有一个 xml 文件和线程池,每个线程在空闲时抓取一个 xml 文件,直到池为空)报告您在此过程中遇到的任何问题。

    您使用的解析方法会影响速度,因为不同的解析库具有不同的行为特征。但是,你确定你需要绝对最快的吗?

    【讨论】:

    • 感谢您的评论。我必须使用多线程。我会按照你的建议开始解决它。
    • 在这种情况下使用解析哪个更好? DOM 还是 SAX?我做了研究,但我无法决定。
    【解决方案3】:

    如果您使用 XSLT(2.0 或更高版本)编写代码,使用 collection() 函数解析源文件,并使用 xsl:result-document 指令编写结果文件,那么您将能够评估效果多线程只需在 Saxon-EE 下运行代码,它会自动将多线程应用于这些结构。通常,根据我的经验,这样的程序可以将速度提高大约 3 倍。

    这是使用函数式声明性语言的好处之一:因为没有可变状态,多线程是无痛的。

    稍后

    我将回答您关于使用 DOM 或 SAX 的补充问题。从我们可以看到,输出文件是输入中 &lt;character&gt; 元素的串联,所以如果你用 XSLT 3.0 编写它,它会是这样的:

    <xsl:mode on-no-match="shallow-skip">
    <xsl:template match="characters">
      <xsl:value-of select="."/>
    </xsl:template>
    

    如果是这种情况,那么肯定没有必要为每个输入文档构建树表示,并且在 SAX 中对其进行编码会相当容易。或者,如果您遵循我使用 Saxon-EE 的建议,您可以使转换流式传输以避免树构建。然而,这是否有用,实际上取决于源文档的大小。你没有给我们任何数字,所以几乎不可能给出关于性能的具体建议。

    如果您要使用基于树的表示,那么 DOM 是您可以选择的最差的表示。这是有六种更好的替代方案的情况之一,但因为它们只有 20% 好,所以世界上大多数人仍然使用 DOM,认为它更“标准”。我会选择 XOM 或 JDOM2。

    如果您准备好花费无限的时间进行编码以获得最后一盎司的执行速度,那么 SAX 就是您的最佳选择。然而,对于大多数项目来说,程序员很贵,而计算机很便宜,所以这是错误的权衡。

    【讨论】:

    • 感谢您的评论。我开始接受@akroy 的建议。完成后我会尝试你的方法。我通过添加我的代码来编辑我的帖子。在这里我需要一些帮助。我使用 SAX 进行解析。我对 Thread Pool.Multi-Threading 做了一些研究。我尝试了一些代码块,但总时间没有变化。如何在上面的代码中添加多个线程?
    猜你喜欢
    • 2011-07-21
    • 2016-05-21
    • 2015-05-14
    • 1970-01-01
    • 2016-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-25
    相关资源
    最近更新 更多