Let's say a given component in your application has these constraints:
- it needs a reference to an object that is expensive to construct
- the expensive object state can be set just once, i.e. it never changes
- it executes in a multi-threaded context
- maximum throughput is required
Constraint #1 seems to call for an instance variable - i.e. you don't want to use a method-local field since the object construction is expensive, as such you don't want to do it each time the object is needed. Constraint #2 implies that a singleton will serve our needs. However, constraint #3 means the singleton must be used in a thread-safe manner - and constraint #4 tells us that we want to avoid synchronization if possible.
Overall, these constraints are similar to the forces that brought the double-checked locking pattern into play some years ago - however, as we subsequently learned, that pattern is broken and is considered an anti-pattern. Don't use it.
There are many suitable alternatives - here's one that uses ThreadLocal to address all four constraints:
- declare a static final ThreadLocal with an initialization which constructs the expensive object
- get the expensive object from the ThreadLocal in the method of interest
Simple - here's a code snippet, using the Java DateFormat class, with well-known thread-safety issues that are effectively moot here (since each thread will have its own copy):
private static final ThreadLocal<SimpleDateFormat> formatters =
new ThreadLocal() {
@Override
public SimpleDateFormat initialValue() {
return new SimpleDateFormat("yyyy-mm-dd_HH.mm.ss.SSS_");
}
};
......
SimpleDateFormat sdfFormatter = formatters.get();
String formattedDate = sdfFormatter.format(new Date());
Credit goes to Jeremy Manson in his post on this topic.
Thanks a lot. Brief and clear.
ReplyDelete