如何将静态最终变量更改为线程局部多线程处理?

时间:2019-03-14 08:45:38

标签: java

我有一个关于多个线程使用相同变量时的竞争条件的问题。

例如:

private static final ContentHandler ORG_OMG_xmi = new RootXMLContentHandlerImpl(
    "org.omg.xmi", new String[] { "xmi" }, "xmi",
    "http://schema.omg.org/spec/XMI/2.1", null);

如何将ContentHandler更改为本地线程,以便可以同时与多个线程一起使用?

2 个答案:

答案 0 :(得分:1)

如评论中所述:只要已知该字段的内容是线程安全的,就不必使多个线程访问的每个静态字段都成为本地线程。很好的例子是典型的不可变类,例如StringInteger,...

也就是说,您可以使用Java8及更高版本将ContentHandler包裹在ThreadLocal中:

private static final ThreadLocal<ContentHandler> ORG_OMG_xmi = ThreadLocal.withInitial(
    () -> new RootXMLContentHandlerImpl("org.omg.xmi", new String[] { "xmi" }, 
            "xmi", "http://schema.omg.org/spec/XMI/2.1", null));

在Java8之前,您可以使用以下方法实现相同的目标:

private static ThreadLocal<ContentHandler> ORG_OMG_xmi =
    new ThreadLocal<ContentHandler>() {
        @Override public ContentHandler initialValue() {
            return new RootXMLContentHandlerImpl("org.omg.xmi", new String[] { "xmi" }, 
                "xmi", "http://schema.omg.org/spec/XMI/2.1", null));
        }
    };

有了ThreadLocal,每个线程都会得到它自己的RootXMLContentHandlerImpl实例,可以通过在get()上调用ThreadLocal来访问它:

ContentHandler myVeryThreadLocalContentHandler = ORG_OMG_xmi.get();

答案 1 :(得分:0)

如果您希望ContentHandler是线程本地的,则可以使用run方法(或run调用的方法)对其进行声明和初始化,例如:

public void run() {
    final ContentHandler ORG_OMG_xmi = new RootXMLContentHandlerImpl("org.omg.xmi", new String[] { "xmi" }, "xmi", "http://schema.omg.org/spec/XMI/2.1", null);
}

这样,就不会在线程之间共享它。