I have already read the interesting discussion on following SO thread about ThreadLocal and its use.
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.
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.
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.
Internally, MDC uses ThreadLocal and it has some predefined functionalities like adding a prefix to every log.
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.
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.
With static
TheadLocal
s 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With