How to initialize ThreadLocal objects in Java
24,560
Solution 1
You just override the initialValue()
method:
private static ThreadLocal<List<String>> myThreadLocal =
new ThreadLocal<List<String>>() {
@Override public List<String> initialValue() {
return new ArrayList<String>();
}
};
Solution 2
The accepted answer is outdated in JDK8. This is the best way since then:
private static final ThreadLocal<List<Foo>> A_LIST =
ThreadLocal.withInitial(ArrayList::new);
Solution 3
Your solution is fine. A little simplification:
private static Whatever getMyVariable()
{
Whatever w = myThreadLocalVariable.get();
if(w == null)
myThreadLocalVariable.set(w=new Whatever());
return w;
}
In Java 8, we are able to do:
ThreadLocal<ArrayList<Whatever>> myThreadLocal = ThreadLocal.withInitial(ArrayList::new);
which uses the Supplier<T>
functional interface.
Author by
B T
Updated on June 15, 2020Comments
-
B T almost 4 years
I'm having an issue where I'm creating a ThreadLocal and initializing it with new ThreadLocal . The problem is, I really conceptually just want a persistent list that lasts the life of the thread, but I don't know if there's a way to initialize something per-thread in Java.
E.g. what I want is something like:
ThreadLocal static { myThreadLocalVariable.set(new ArrayList<Whatever>()); }
So that it initializes it for every thread. I know I can do this:
private static Whatever getMyVariable() { Whatever w = myThreadLocalVariable.get(); if(w == null) { w = new ArrayList<Whatever>(); myThreadLocalVariable.set(w); } return w; }
but I'd really rather not have to do a check on that every time it's used. Is there anything better I can do here?
-
B T about 11 yearsInteresting comment about Java 8's strange looking ability to initialize less verbosely.
-
ZhongYu about 11 yearsInitially it was designed as
new ThreadLocal<>( lazyInitializer )
. Doug Lea protested that it adds a new field to each ThreadLocal instance. The design was changed to use a factory method, which instantiates a subclass of ThreadLocal. Existing programs that usenew ThreadLocal()
will still get a good old ThreadLocal instance without any change. -
kevinarpe almost 9 yearsI know this Q&A is a bit old now, but as of writing, the official JDK8 docs have an example in the class description of exactly this -- using
initialValue()
. Ref: docs.oracle.com/javase/8/docs/api/java/lang/ThreadLocal.html -
kevinarpe almost 9 yearsAlso there is now a lambda-friendly static factory method that will help, e.g.,
ThreadLocal.withInitial(ArrayList::new)
-
user1950349 almost 8 years@JonSkeet I am not sure whether I should be using
ThreadLocal
in one of my SO question here. Wanted to see if you can help out. I haven't got any response yet and I was confuse whether using ThreadLocal is the right option. -
Michael almost 7 yearsThanks. The field probably shouldn't be capitilised because it's not a constant (the list is mutable). If it were constant, there'd be no need for it to be thread local. You're also using raw types which will introduce a compiler warning. It should be
ThreadLocal<List<Foo>>
. :) -
Oliv almost 7 yearsThe field is a constant reference, doesn't matter that the referenced object is mutable.
-
Michael almost 7 yearsThe convention is to capitalise constants, not constant references. See chapter 4 of Effective Java, which is about as authoritative as a Java reference can get: "By convention, such fields have names consisting of capital letters, with words separated by underscores. It is critical that these fields contain either primitive values or references to immutable objects. A final field containing a reference to a mutable object has all the disadvantages of a nonfinal field. While the reference cannot be modified, the referenced object can be modified—with disastrous results."
-
Oliv almost 7 yearsThis talks about usage of constants, not the naming style. Whenever a field is
static final
, it is a constant. Anyway, it's just a convention. I use this one and as far as I remember, most folks do too. -
Michael almost 7 years"Whenever a field is
static final
, it is a constant" hahahaha -
Oliv over 6 yearsOK, I tried to look up official definition of a constant. Oracle naming conventions don't define it. Checkstyle defines it as "static final field". Google conventions define it as "static final fields whose contents are deeply immutable". So there are contradictions. At least some people (including myself) define it as any "static final" field, so let's put aside this unrelated discussion.
-
Michael over 6 yearsConstant: "a situation that does not change". Mutable: "liable to change". If you didn't want to carry on the discussion, you didn't have to reply. It's been months. However, you're wrong and I'm not letting you off the hook that easy ;)
-
Oliv over 6 yearsIs
public static final String TABLE_NAME = "myTable"
a constant? It's a reference to a DB table, which is mutable. You can dereference it and mutate it. The distinction is set somewhat arbitrarily, that's what I say. Not that you are wrong. But many people define it as I do. -
Michael over 6 yearsYes, of course that's a constant. It will always represent the string "myTable". The fact that it's used to access some other mutable state is irrelevant. The useful information that's conveyed by the capitalised naming convention is that the object will never change. If it will never change, I know it's inherently thread-safe and can be sure that any interaction will be free from side-effects. I can use it in a pure function. By capitalising mutable static final variables, there is no useful information conveyed about the contents at all and you're undermining the entire point of doing it.
-
Santosh Ravi Teja about 4 yearsHow to specify array list
capacity
orsize
like this ArrayList<>(size) ? in this thread local implementaiton ?