1

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

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

但是我不确定这是否是一个好主意,我也可以选择将其设为实例变量,因为我正在使用它(正如我在单例中所说的那样)。

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

4

3 回答 3

4

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

因为 Java 编程语言是多线程的,所以类或接口的初始化需要仔细同步,因为其他一些线程可能同时尝试初始化同一个类或接口。还有一种可能性是,作为该类或接口初始化的一部分,可以递归地请求类或接口的初始化;例如,类 A 中的变量初始化器可能会调用不相关的类 B 的方法,而后者又可能调用类 A的方法。Java 虚拟机的实现负责通过使用以下程序。


请参阅 JLS 的第12.4.2节,其中详细描述了这件事。

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

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

于 2012-06-12T18:37:26.380 回答
1

静态成员将确保创建一个新的 ThreadLocal,但对于每个新线程,该 ThreadLocal 的初始值将为空。您可以通过重写 initialValue() 方法轻松地提供特定于线程的初始值。一种方法是使用匿名内部类 EG

static final ThreadLocal<HashMap> bindingContext = new ThreadLocal<HashMap>() {
    @Override protected HashMap initialValue() {return new HashMap();}
    };
于 2014-03-11T15:16:45.843 回答
1

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

private ThreadLocal<Map<String,String>> bindingContext = ThreadLocal.withInitial(HashMap::new);
于 2019-06-10T04:09:04.887 回答