要求在多线程环境中明确 TransformerFactory 的 XSLT Transformer

Posted

技术标签:

【中文标题】要求在多线程环境中明确 TransformerFactory 的 XSLT Transformer【英文标题】:Request clarity on TransformerFactory's XSLT Transformer in multithreaded environment 【发布时间】:2020-01-23 20:10:44 【问题描述】:

Transformer 文档 (https://docs.oracle.com/javase/8/docs/api/javax/xml/transform/TransformerFactory.html#newTransformer-javax.xml.transform.Source-) 说

必须注意不要在同时运行的多个线程中使用此 Transformer。

当我在多线程环境中使用相同的 Transformer 对象时,会发生什么情况? 为什么我们不能使用带有 2 个线程的同一个 Transformer 对象?

如果我的 XSLT 源是固定的,我是否可以缓存 Transformer 对象,这样我的所有请求都将使用相同的 Transformer,而不是在每个请求上重新创建它?

【问题讨论】:

【参考方案1】:

要编译和缓存您的固定代码,请使用newTemplates 创建一个Templates 对象https://docs.oracle.com/javase/8/docs/api/javax/xml/transform/TransformerFactory.html#newTemplates-javax.xml.transform.Source-,然后对于多线程环境中的每次执行,在Templates 对象上使用newTransformer 创建一个新的Transformer.

【讨论】:

【参考方案2】:

像 Transformer 这样的 JAXP 类是接口,它们有多种实现(目前最广泛使用的两个是 Xalan 和 Saxon)。打破多线程规则的实际效果将取决于您使用的处理器;但在这两种情况下,它们都将是不可预测的。 Transformer 可能会保存变量的当前状态和动态执行上下文,因此您真的不希望两个转换覆盖彼此的变量。

为了避免每次使用都重新编译样式表的成本,您需要缓存 Templates 对象,而不是 Transformer 对象。理论上,您可以连续重用 Transformer 在单个线程中连续执行多个转换,但没有意义:只需为每个新转换创建一个新的 Transformer(从缓存的模板)。

要注意的另一件事是 DOM 不是线程安全的,即使在只读模式下也是如此。不允许两个转换同时访问同一个 DOM 树。如果您确实需要在多个转换之间共享源文档,那么最好的方法最终取决于您使用的是 Xalan 还是 Saxon。

【讨论】:

感谢您的澄清。这真的很有帮助。还有一个问题,当我们直接将Transformer 与不同的XSLT 一起使用时,它会消耗太多的java 元空间并且metaspaceInUse 会不断增加?这是预期的行为吗?背后的原因是什么? 您需要将其作为一个单独的问题提出,提供有关您正在使用的 XSLT 处理器、您正在运行的样式表以及您正在进行的测量的完整信息。 我提出了一个单独的问题 - ***.com/questions/58091381/…

以上是关于要求在多线程环境中明确 TransformerFactory 的 XSLT Transformer的主要内容,如果未能解决你的问题,请参考以下文章

在多线程环境中使用 PyCurl 时程序消耗的内存不断增长

可以在多线程环境中使用单个 QueueConnection 吗?

如何在多线程环境中捕获 SIGABRT?

在多线程环境中使用 .Net UdpClient

在多线程环境中写入时的 Swift 数组复制

iPhone:在多线程环境中发布 UIViewController 时出现问题