Java 输入流/XSL 线程安全

标签 java multithreading xslt

我有一些最初用于单线程处理的代码,现在由多个线程使用。我在未修改且通常工作正常的 xsl 上遇到了奇怪的 xsl 解析错误。

我不寻求代码修正,我将通过我自己的研究重构此类以实现线程安全。欢迎提供有关此问题的提示,但对于答案来说不是必需的。
我寻求解释可能/可能发生的情况,从而产生下面看到的奇怪错误

例如线程A进入代码X行,在Y行停止,线程B进入X行,读取流S,停止。线程 A 现在执行 Z 来传输 S 并损坏它...等等。我模糊的预感是,当 2 个线程同时操作/读取对象“xsl”时,它会以某种方式损坏,但我缺乏对 InputStream 对象和 Source 对象如何进行的了解在 api 内部工作。

XSL:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  ... 
</xsl:stylesheet>

样式表应该没问题。如果您不这么认为,请告诉我。

错误:

[Fatal Error] :1:33: The encoding declaration is required in the text declaration.
[Fatal Error] :1:2: Content is not allowed in prolog.
Couldn't create transformer object for xsl javax.xml.transform.TransformerConfigurationException: Could not compile stylesheet

这些错误发生了很多次,并且一直持续到应用程序重新启动为止。这些显然都指向一个错误的 xsl。但我确实验证了该文件没有损坏。

Java代码:

public class IntegrationRequest {

  private static Source xsl; // data that i believe got corrupted
  private static Transformer inputTransformer;
  private static JAXBContext createContext;

  ...

  // this public method is now executed by multiple threads at once
  public String getResponse()  {
    createTransformerInstance(); // err thrown in here
    String xmlRequest = getXmlRequestString();
    String response = executeRequest(createHttpConnection(), xmlRequest);
    return response;
  }

  private static Transformer createTransformerInstance() {
    if (inputTransformer == null) {
        TransformerFactory factory =  TransformerFactory.newInstance();
        try {
            inputTransformer = factory.newTransformer(getXSLTemplate("/Integration_Request.xsl"));
        } catch (TransformerConfigurationException e) {
            if (log.isErrorEnabled()) {
                log.error("Couldn't create transformer object for xsl ", e);
            }
        }
    }
    return inputTransformer;
  }

  private static Source getXSLTemplate(String fileName) {
    if (xsl == null) {
        InputStream xslInputStream = IntegrationRequest.class.getClassLoader().getResourceAsStream(fileName);
        xsl = new StreamSource(xslInputStream);
    }
    return xsl;
  }

}

注意 getXSLTemplate 如何缓存 xsl - 应用程序将保留该错误数据直到重新启动。这是我的理论的基础,即它在第一次加载时被多个线程损坏。

最佳答案

这些错误表明样式表解析失败 - XML 解析器在读取样式表文档时没有看到有效的 XML。发生这种情况很可能是因为两个或多个线程开始创建样式表,所有线程都在 xsl 变量中使用相同的 InputStream。一种可能的情况是:

  • 线程 1 第一次调用 getResponse,创建 xsl,线程 1 开始从 xsl 读取。
  • 线程 2 调用 getResponse,也没有看到非空 transformer,开始从同一个 xsl 读取,从而破坏了解析线程 1 中的进程。

请注意,Transformer 也不是线程安全的类。您应该使用 javax.xml.transform.Templates 来代替,并从 Templates 为每个转换创建一个 Transformer

关于Java 输入流/XSL 线程安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35900809/

相关文章:

python - 共享内存复杂的可写数据结构

xslt - XPath 1.0 选择 sibling 的不同属性

java - Java 6 中默认支持 xinclude 吗?

objective-c - 使用cocoa的performSelectorOnMainThread数千次的安全性

java - 如何在 Netty channel 处理程序中安全地执行阻塞操作?

javascript - 使用 JavaScript 的 XSL 参数

java - Akka http 使用 java - 从 RequestEntity 获取字符串

java - 仅当未在构造函数中设置时才 Autowiring 变量

java - 如何使用 Spring-Boot 运行 cxf-xjc-plugin?

linux 中的 java 版本