简体   繁体   中英

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.

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.

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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM