【问题标题】:how to change a static final variable to thread local Multithreading? [duplicate]如何将静态最终变量更改为线程本地多线程? [复制]
【发布时间】:2019-08-05 02:14:59
【问题描述】:

我对多个线程使用同一个变量时的竞争条件有疑问。

例如:

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 更改为线程本地,以便同时将它用于多个线程?

【问题讨论】:

  • static final 的重点是声明一个可在此类外部访问且不可变的变量。无法更新它的值。我不知道你想用这个变量做什么,但我认为你需要明确你想做什么。
  • 是的,我在类外同时使用多个线程访问此变量,因此我必须将其更改为线程本地
  • 如果它不是线程安全的,您只需将其设为本地即可。例如,在多个线程之间共享public static final String 没有任何问题。
  • 我知道问题出在 private static final ThreadLocal ORG_OMG_xmi = new ThreadLocal( "org.omg.xmi", new String[] { "xmi" }, "xmi", "schema.omg.org/spec/XMI/2.1", null);不工作
  • 只要使用ThreadLocal

标签: java


【解决方案1】:

如果您希望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);
}

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

【讨论】:

    【解决方案2】:

    正如 cmets 中提到的:只要已知字段的内容是线程安全的,就不需要将多个线程访问的每个静态字段都设为线程本地。这里很好的例子是典型的不可变类,如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 实例,可以通过在ThreadLocal 上调用get() 来访问:

    ContentHandler myVeryThreadLocalContentHandler = ORG_OMG_xmi.get();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-30
      • 2019-05-11
      • 1970-01-01
      • 2011-07-17
      • 2013-08-31
      相关资源
      最近更新 更多