首页 > 解决方案 > 使用 ThreadLocal.get() 获取不确定值

问题描述

我正在使用 org.apache.xalan.transformer.TransformerImpl 对 org.w3c.dom.Document 进行一些转换。这是代码:

    protected Document transform(Document document, OlapWidget olapWidget, String name, String description) throws TransformerException, IOException {
        Transformer transformer = XmlUtils.getTransformer(getSession(), xslUri, true);
        DOMResult domResult = new DOMResult();
        transformer.setParameter("reportTitle", StringUtils.coalesce(name, ""));
        transformer.setParameter("reportDescription", StringUtils.coalesce(description, ""));
        transformer.setParameter("hideSpans", isHideSpans() ? "yes" : "no");
        transformer.transform(new DOMSource(document), domResult);
        return (Document) domResult.getNode();
    }

据我了解,它使用模板转换了一些文档。在本例中,此模板是 String xslUri。此模板只是一个 .xsl 文件。该文件使用我的一个类:

<lxslt:component prefix="XsltHelper"
    functions="hideTotals">
    <lxslt:script lang="javaclass" src="com.texunatech.nss.util.xsl.XsltUtils"/>
</lxslt:component>

这个类的代码

public class XsltUtils {
    public static String hideTotals() {
        OlapWidget report = OlapReportHolder.getReport();
        if (report == null) {
            return "no";
        } else {
            return Arrays.asList(OlapConstants.PROVIDER_AGGREGATED_ALL_DATASET, OlapConstants.PROVIDER_ALL_DATASET, OlapConstants.PROVIDER_DATASET,
                    OlapConstants.PROVIDER_AGGREGATED_ALL_DATASET_HIST, OlapConstants.PROVIDER_ALL_DATASET_HIST, OlapConstants.PROVIDER_DATASET_HIST).contains(report.getDataSlice().getDataCubeCode()) ? "yes" : "no";
        }
    }
}

所以,问题出在OlapReportHolder.getReport(). 有时我用这种方法得到一些对象。但更多时候我使用这种方法得到 null ,这是不正确的。它看起来完全随机。

OlapReportHolder 中的代码是:

public class OlapReportHolder implements Serializable {
    
    private static final ThreadLocal<OlapWidget> reportHolder = new ThreadLocal<OlapWidget>();

    public static void setReport(OlapWidget report) {
        reportHolder.set(report);
    }


    public static OlapWidget getReport() {
        return reportHolder.get();
    }
}

如您所见,它使用 ThreadLocal。这段代码有什么问题?为什么结果不稳定?我应该总是用这种方法得到一个对象,但我没有。这个怎么运作?我该如何解决这个问题?

标签: javathread-local

解决方案


如果setReport在一个线程和getReport另一个线程中调用,那么显然你不会得到你之前设置的东西。


推荐阅读