Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ThreadLocal vs Parameter Passing - What to choose at Interface Design?

I have already read the interesting discussion on following SO thread about ThreadLocal and its use.

  • When and how should I use a ThreadLocal variable?
  • Purpose of ThreadLocal?
  • How does ThreadLocal usage reduce reusability
  • Is it OK to use ThreadLocal for storing the requested Locale?

This questions is more towards a design time choice. My scenario is like this

If I have a value object in a web application that may need to used inside same thread by almost all steps. I can think of two interface design options like below

Approach #1 Using Method Parameter Passing.

I have so far focused on coming up with a interface that can have methods with parameters of a value object interface.

For example:

public interface SomeDataProcessorInterface {

public void processSomething(SomeValueObjectInterface vo);

}

public interface SomeValueObjectInterface extends Serializable {}

Aproach #2 Using ThreadLocal

In this approach I can have a interface with no method parameter and just create a static class to access my value objects using a threadlocal.

For example:

public interface SomeDataProcessorInterface {

public void processSomething();

}

public interface SomeValueObjectInterface extends Serializable {}

public Class StaticClass {

    private static ThreadLocal<SomeValueObjectInterface> threadLocalVO = new ThreadLocal<SomeValueObjectInterface>();

     public static ThreadLocal getThreadLocal() {
        return threadLocal;
      }

Which approach is better? and why?

Which one of these implementation is going to have less chances of memory leak?

Which one of these implementation is going to be good for Java Garbage Collector?

I read thru some of the points in other thread however I am still not clear which approach is better if I am starting from scratch.

like image 533
software.wikipedia Avatar asked Oct 10 '13 20:10

software.wikipedia


People also ask

When should I use ThreadLocal?

ThreadLocal is useful, when you want to have some state that should not be shared amongst different threads, but it should be accessible from each thread during its whole lifetime. As an example, imagine a web application, where each request is served by a different thread.

What is the purpose of declaring a variable of type ThreadLocal?

It enables you to create variables that can only be read and write by the same thread. If two threads are executing the same code and that code has a reference to a ThreadLocal variable then the two threads can't see the local variable of each other.

Does MDC use ThreadLocal?

Internally, MDC uses ThreadLocal and it has some predefined functionalities like adding a prefix to every log.


3 Answers

If you have a choice between passing something as a method parameter or via ThreadLocal storage, you should 99.99999% of the time pass it as a method parameter. The main purpose of ThreadLocal storage is to handle cases where one is calling a method indirectly (meaning one is asking some other method to in turn call the method of interest), one needs to pass information to the inner method, and the method in the middle provides no convenient conduit for passing that information. If there were no "middle layer", one could simply add the additional parameter to the inner method's signature (generally the inner method would only be called by the code which has the information, so adding the parameter at both the method definition and call site should be no problem). In some cases, however, middle layers exist and must be worked with.

For sample, consider a ShapeCollection which includes a DrawAll method which calls Draw on all its shapes. An application defines some shapes which are slow to render "nicely", and thus adds an option to each window to select whether to have such shapes appear as a place-holder rather than a detailed rendering. If Shape had been designed with such needs in mind, its Draw method could have included an asPlaceHolder parameter, and ShapeCollection's DrawAll could have accepted such a parameter and passed it to each shape. If the designer of Shape hasn't anticipated such a need, however, ShapeCollection isn't going to support it.

If each fancy shape objects's Draw method will only be used for the purpose of updating one particular window, the shape could hold a reference to that window, and use that window's "Use placeholders" option in determining how it should render itself. If, however, there could be multiple windows showing views of the shape, and each should support its own rendering options, that approach may not work. Such an approach may also have problems if the Draw method gets used to render things for the clipboard, a printer, or other medium. Having a window's drawing code construct a DrawingOptions object, create a thread-local reference to it, call DrawAll, and then erase that thread-local reference would be inelegant, but it would provide a means for calls to DrawAll to pass drawing options to the inner Draw method--something that would otherwise not be possible.

like image 118
supercat Avatar answered Sep 20 '22 16:09

supercat


It is a design issue, and depends on your case.

If SomeValueObjectInterface have meaning in the context of service's business logic, then (I believe) it shall be a parameter, but if you consider it as data for crosscutting concerns (aspects which are not implemented as aspects), and it is not a parameter of business logic, then use ThreadLocal.

By the way don't forget to clear the ThreadLocal in a finally block, or you would encounter memory-leak issues (which are mostly hard to find).

And there is no difference for GC, because if you don't forget to clear the ThreadLocal then the objects in both approaches would be in eden.

like image 24
Amir Pashazadeh Avatar answered Sep 19 '22 16:09

Amir Pashazadeh


With static TheadLocals you risk leaking memory if you forget to remove the element. You can always avoid this by removing the element before returning from your method. I wouldn't recommend this approach.

Your 1st approach is already thread safe, as it stands, since the parameter will be local to that method call only. Use this one.

like image 31
Sotirios Delimanolis Avatar answered Sep 23 '22 16:09

Sotirios Delimanolis