1

I have a question about the race condition when multiple threads use the same variable.

For example:

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);

How can I change ContentHandler to thread local so I can use it with multiple threads at the same time?

khelwood
  • 55,782
  • 14
  • 81
  • 108
JavaNinja
  • 49
  • 7
  • The point of `static final` is to declare a variable that is accessible outside this class and that is immutable. It's not possible to update it's value. I don't know what do you wanna do with this variable but I think you need to explicit what you wanna do. – Maxouille Mar 14 '19 at 08:53
  • yes i access this variable outside the class with multiple threads at the same time so i must change it to thread local – JavaNinja Mar 14 '19 at 08:56
  • You only have to make it thead local, if it is not thread safe.There is for example nothing wrong with a `public static final String` shared between multiple threads. – dpr Mar 14 '19 at 08:57
  • i know the problem is private static final ThreadLocal ORG_OMG_xmi = new ThreadLocal( "org.omg.xmi", new String[] { "xmi" }, "xmi", "http://schema.omg.org/spec/XMI/2.1", null); doesnt work – JavaNinja Mar 14 '19 at 08:59
  • Just use `ThreadLocal` – Lino Mar 14 '19 at 08:59
  • @GhaithBriki why does that example not work? – XtremeBaumer Mar 14 '19 at 09:05
  • Just read [this answer](https://stackoverflow.com/a/15369526/4323935) – dpr Mar 14 '19 at 09:06

2 Answers2

1

As mentioned in the comments: There is no need to make every static field accessed by multiple threads thread local as long as the content of the field is known to be thread-safe. Good examples here are the typical immutable classes like String, Integer, ...

That said, you can wrap your ContentHandler in a ThreadLocal like this with Java8 and above:

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));

pre Java8 you can achieve the same with this:

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));
        }
    };

With ThreadLocal every thread will get it's own instance of RootXMLContentHandlerImpl which can be accessed by calling get() on the ThreadLocal:

ContentHandler myVeryThreadLocalContentHandler = ORG_OMG_xmi.get();
dpr
  • 10,591
  • 3
  • 41
  • 71
0

If you want ContentHandler to be thread local then you can declare and initialise it in run method (or a method that is invoked by run), e.g.:

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);
}

This way, it won't be shared between threads.

Darshan Mehta
  • 30,102
  • 11
  • 68
  • 102