32

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
  • 57,525
  • 34
  • 189
  • 207

4 Answers4

47

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>();
        }
    };
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 2
    I 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: https://docs.oracle.com/javase/8/docs/api/java/lang/ThreadLocal.html – kevinarpe Jul 17 '15 at 06:39
  • 10
    Also there is now a lambda-friendly static factory method that will help, e.g., `ThreadLocal.withInitial(ArrayList::new)` – kevinarpe Jul 17 '15 at 06:44
  • @JonSkeet I am not sure whether I should be using `ThreadLocal` in one of my SO question [here](http://stackoverflow.com/questions/37125694/initialize-socket-timeout-value-in-httpclient-and-then-use-it-with-resttemplate). 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. – user1950349 May 10 '16 at 20:57
25

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);
Oliv
  • 10,221
  • 3
  • 55
  • 76
  • 1
    Thanks. 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>`. :) – Michael Jun 14 '17 at 13:08
  • The field is a constant reference, doesn't matter that the referenced object is mutable. – Oliv Jun 14 '17 at 13:36
  • 1
    The 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." – Michael Jun 14 '17 at 13:44
  • This 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. – Oliv Jun 14 '17 at 14:09
  • "Whenever a field is `static final`, it is a constant" [hahahaha](https://www.google.com/search?q=define:+constant) – Michael Jun 14 '17 at 14:21
  • OK, 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. – Oliv Dec 04 '17 at 20:22
  • Constant: "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 ;) – Michael Dec 04 '17 at 21:44
  • Is `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. – Oliv Dec 05 '17 at 06:43
  • Yes, 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. – Michael Dec 05 '17 at 10:15
20

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.

Michael
  • 41,989
  • 11
  • 82
  • 128
ZhongYu
  • 19,446
  • 5
  • 33
  • 61
  • 1
    Interesting comment about Java 8's strange looking ability to initialize less verbosely. – B T Mar 12 '13 at 21:01
  • 1
    Initially 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 use `new ThreadLocal()` will still get a good old ThreadLocal instance without any change. – ZhongYu Mar 12 '13 at 21:20
  • How to specify array list `capacity` or `size` like this ArrayList<>(size) ? in this thread local implementaiton ? – Santosh Ravi Teja Apr 10 '20 at 15:21
0

Thread local storage is the area where each thread have it's own sperate variable so that concurrency and parallelism can be achieved.

Here is the example to initialize ThreadLocalVariable of SimpleDateFormat- object.

public class ThreadLocalTest {


private static ExecutorService threadPool = Executors.newFixedThreadPool(10);


//Thread Local SimpleDateFormat
public static ThreadLocal<SimpleDateFormat> dateFormatter = new ThreadLocal<>() {
    @Override
    protected SimpleDateFormat initialValue() {
        return new SimpleDateFormat("yyyy-MM-dd");
    }

    @Override
    public SimpleDateFormat get() {
        return super.get();
    }
};


public static void main(String[] args) throws InterruptedException {

    for (int i = 0; i < 100; i++) {

        threadPool.submit(()-> {
            String birthDate = new ThreadLocalV3().birthdate(100);
            System.out.println(birthDate);
        });

    }

    Thread.sleep(1000);
}


public String birthdate(int userId) {

    Date birthDate = new Date(); //instead of new Date()  suppose we need to fetch birthdate bu userId

    //now each thread will have it's own sdf object
    final SimpleDateFormat sdf = ThreadLocalTest.dateFormatter.get();

    return sdf.format(birthDate);
}
}

After java 8 versions, you can achieve ThreadLocal initialization using lambda expressions as below:

public static ThreadLocal<SimpleDateFormat> dateFormatter = ThreadLocal.withInitial(()-> new SimpleDateFormat("yyyy-MM-dd"));