如何在Java中初始化ThreadLocal对象

B T*_*B T 21 java static-block thread-local

我遇到了一个问题,我正在创建一个ThreadLocal并用新的ThreadLocal初始化它.问题是,我在概念上只是想要一个持久的列表,这个列表会延续线程的生命,但我不知道是否有办法在Java中初始化每个线程的东西.

例如,我想要的是:

ThreadLocal static {
  myThreadLocalVariable.set(new ArrayList<Whatever>());
}
Run Code Online (Sandbox Code Playgroud)

这样它就可以为每个线程初始化它.我知道我可以这样做:

private static Whatever getMyVariable() {
  Whatever w = myThreadLocalVariable.get();
  if(w == null) {
    w = new ArrayList<Whatever>();
    myThreadLocalVariable.set(w);
  }
  return w; 
}
Run Code Online (Sandbox Code Playgroud)

但是每次使用它时我都不需要检查它.我能在这做什么更好的事情吗?

Jon*_*eet 34

您只需覆盖该initialValue()方法:

private static ThreadLocal<List<String>> myThreadLocal =
    new ThreadLocal<List<String>>() {
        @Override public List<String> initialValue() {
            return new ArrayList<String>();
        }
    };
Run Code Online (Sandbox Code Playgroud)

  • 现在还有一个lambda友好的静态工厂方法,它将有助于,例如,`ThreadLocal.withInitial(ArrayList :: new)` (7认同)
  • 我知道这个问答现在有点老了,但在撰写本文时,官方 JDK8 文档在类描述中提供了一个示例——使用 `initialValue()`。参考:https://docs.oracle.com/javase/8/docs/api/java/lang/ThreadLocal.html (2认同)

Zho*_*gYu 17

你的解决方案很好.一点点简化:

private static Whatever getMyVariable() 
{
    Whatever w = myThreadLocalVariable.get();
    if(w == null) 
        myThreadLocalVariable.set(w=new Whatever());
    return w; 
} 
Run Code Online (Sandbox Code Playgroud)

在Java 8中,我们能够:

ThreadLocal<ArrayList<Whatever>> myThreadLocal = ThreadLocal.withInitial(ArrayList::new);
Run Code Online (Sandbox Code Playgroud)

它使用Supplier<T>功能界面.


Oli*_*liv 10

接受的答案在JDK8中已经过时.这是自那时以来最好的方式:

private static final ThreadLocal<List<Foo>> A_LIST = 
    ThreadLocal.withInitial(ArrayList::new);
Run Code Online (Sandbox Code Playgroud)