Good practice for using ThreadLocal in Java
I have a question as to how should I use ThreadLocal
.
Context and situation
There are several singleton objects that are used ThreadLocal
to create one copy per stream. This singleton object has a function foo()
.
public class SingletonA {
protected static ThreadLocal<SingletonA> singleton = new ThreadLocal<SingletonA>() {
@Override
protected SingletonA initialValue() {
return new SingletonA();
}
};
private SingletonA() { ... }
public static SingletonA getInstance() { return singleton.get(); }
public static void remove() { singleton.remove(); }
public static void foo() { ... }
}
... There is SingletonB, SingletonC, etc.
There is a singleton repository that caches the singlets above ThreadLocal
. This class is also a ThreadLocal
singleton -
public class SingletonRepo {
protected static ThreadLocal<SingletonRepo> singleton = new ThreadLocal<SingletonRepo>() {
@Override
protected SingletonRepo initialValue() {
return new SingletonRepo();
}
};
private SingletonRepo() { ... }
public static SingletonRepo getInstance() { return singleton.get(); }
public static void remove() { singleton.remove(); }
public SingletonA singletonA;
// same thing for singletonB, singletonC, ...
public static init() {
// Caching the ThreadLocal singleton
singletonA = SingletonA.getInstance();
// Same thing for singletonB, singletonC ...
}
}
I am currently accessing singlons ThreadLocal
viaSingletonRepo
public class App {
public SingletonRepo singletonRepo;
public static void main(String [] args) {
singletonRepo = SingletonRepo.getInstance();
singletonRepo.init();
singletonRepo.singletonA.helperFunction();
}
}
Question
As you saw in the above context, in order to access the singlons ThreadLocal
, I first cached them in SingletonRepo
. When I need to use a singleton ThreadLocal
, I get it from a cache reference. I have the following questions -
- Wrong practice to access syntax
ThreadLocal
via copy cache? - Is it better to always refer to the syntax
ThreadLocal
viaSingletonA.getInstance()
(callget()
to Singleton object)?
source to share
A local cached copy of the stream is great as it is simpler and more efficient. A cached copy where you are not sure if it is a local thread can be a problem.
One singleton, by definition, means that there can only be one. I would not what you have as a singleton, and you have one for each thread.
I would include () your thread local object in its constructor.
BTW Your ThreadLocal should be private static final
I suspect.
source to share
It is not entirely clear what you want to achieve. The aspects of ThreadLocal
search performance are negligible, so "caching" doesn't really make much sense, especially since you still have to search for a cache instance.
It has been more useful if the type SingletonA
, SingletonB
, SingletonC
etc. did not ThreadLocal
, so SingletonRepo
was the only instance supported via ThreadLocal
, while other instances are supported SingletonRepo
and therefore implicitly thread-local. However, its implementation constructors SingletonA
, SingletonB
, SingletonC
etc. Must be accessible with SingletonRepo
.
What amazes me, given the way you currently implement it, is that there is a method remove
for the singleton classes as well as the repo class, which therefore allows for inconsistencies. For example, I can call SingletonRepo.getInstance().init()
, and then SingletonA.remove()
et voilà, you created a situation for your current thread, where it SingletonRepo.getInstance().singletonA
contains a reference to an instance, and SingletonA.singleton
does not matter, and will create a new instance on the next call getInstance()
, so that two different instances exist simultaneously for the same thread ...
source to share