Java中的ThreadLocal初始化?

时间:2012-06-12 18:27:19

标签: java

我正在构建一个将ThreadLocal作为实例变量的单例,这个单例有一个可以被多个线程访问的方法,并且它被懒惰地实例化。现在我正在考虑这样的事情:

static final ThreadLocal<HashMap> bindingContext = new ThreadLocal<HashMap>();

但是我不确定这是不是一个好主意,我也可以选择让它成为一个实例变量,因为我正在使用它(正如我在单身人士所说的那样)。

所以问题是,初始化该类变量的最佳位置在哪里,或者它应该是一个类变量?

3 个答案:

答案 0 :(得分:4)

保证静态初始化器以线程安全的方式执行。 JLS特别提到了这一点:

  

因为Java编程语言是多线程的,所以初始化   一些类或接口需要仔细同步,因为有些   其他线程可能正在尝试初始化相同的类或接口   同时。初始化也有可能   可以递归地请求类或接口作为其一部分   初始化该类或接口;例如,一个变量   A类中的初始化程序可能会调用不相关的B类的方法,   这可能反过来调用A类的方法。执行   Java虚拟机负责照顾   使用以下内容进行同步和递归初始化   过程


请参阅详细描述此内容的12.4.2 of JLS部分。

编辑:你正在尝试的非常好。来自ThreadLocal的javadoc:

  

ThreadLocal实例通常是类中的私有静态字段   希望将状态与线程相关联(例如,用户ID或   交易ID)。

答案 1 :(得分:1)

静态成员将确保将创建新的ThreadLocal,但每个新线程的ThreadLocal的初始值将为null。您可以通过覆盖initialValue()方法轻松提供特定于线程的初始值。一种方法是使用匿名内部类E.G.

static final ThreadLocal<HashMap> bindingContext = new ThreadLocal<HashMap>() {
    @Override protected HashMap initialValue() {return new HashMap();}
    };

答案 2 :(得分:0)

使用Lamda时,我们可以这样写:

private ThreadLocal<Map<String,String>> bindingContext = ThreadLocal.withInitial(HashMap::new);