Java Spring Bean中的实例变量

Şer*_*cet 4 java heap spring multithreading thread-safety

我正在开发一个Java Spring MVC项目,我犹豫在Java Spring Bean中使用实例变量。我想问一些有关此主题的问题。

我在Java Spring Bean中使用了一个实例变量,其类型为String。

private String abc = "hell";
Run Code Online (Sandbox Code Playgroud)

众所周知,Java Spring的默认范围是Singleton,它们是在项目启动时构造的。它是单个实例,我的实例变量必须是线程安全的。

我在Bean的方法中使用了此变量“ abc”,当多个线程访问它们时,是否会破坏每个线程的数据一致性?

例如,线程1到达bean并采用abc变量将其更改为“ hello”。那时,线程1引用了abc变量点“ hell”还是“ hello”?我对这个话题感到困惑。

我将String abc变量设置为ThreadLocal对象,以提供每个线程拥有其自己的abc变量ThreadLocal

因为每个线程都拥有自己的变量,并且在完成工作后返回线程池,该线程池由容器管理。但是,返回池时,ThreadLocal对象不会被破坏,并且会导致内存泄漏。

而且,String对象是不可变的,因此在理论上它会引起多线程问题吗?

每个线程自己拥有自己的String变量吗?例如,线程1触发,然后启动方法调用,并创建单独的String变量“ abc”,而线程2触发,然后创建新的String变量“ abc”,它们是否会相互破坏“ abc”变量?

我真的很想知道这种用法的概念,并渴望学习答案。

Bor*_*der 5

我将尝试分别解决您的问题。

abc在Bean的方法中使用了此变量,当多个线程到达它们时,是否会破坏每个线程的数据一致性?

这个问题的简短答案是肯定的。如果您abc在其中写入了另一个值,Thread可能会或可能不会从另一个线程看到它。这就是volatile引入关键字的原因。

我想在其中加入可变的 singleton bean,Spring然后在同步和使用时要小心volatile

数据不会被“破坏”,因为正如您所指出的那样,它String是不可变的。但是一个线程可能看不到另一个已更改的值abc

所以你有一个变量abc;

  1. abc =“嗨。”
  2. 线程1读abc为“ Hi”。
  3. 线程1 abc通过写入以下引用进行更改:abc="Hello."
  4. 线程2读取abc,不清楚是否abc读取“ Hi”。或“你好”。

我将String abc变量设为ThreadLocal对象,以提供每个线程都拥有自己的abc变量

ThreadLocal用于使每个线程获得不同的变量实例。当Web服务器使用线程预请求模型时,这通常用于将状态绑定到Web服务器中的线程。

Tomcat的7 解决ThreadLocal泄漏问题。如果不从线程中删除已设置的变量,则将导致泄漏。甚至更糟的是,一个请求将从另一个请求的上下文中获取项目。当线程在上下文中留有线程的情况下将其检入池,ThreadLocal然后由另一个请求检出该线程时,会发生这种情况。

Tomcat 7竭力检测这些问题并换出线程以删除其ThreadLocal变量。这很昂贵,可以通过ThreadLocal正确使用来避免。

您需要清除ThreadLocalservlet过滤器中的变量。

所以:

如果您有一个变量abc要在一个线程中写入,并且要使该更改在其他线程中不可见,则可以使用ThreadLocal,但是在每次请求后都要非常小心地清除状态。

如果您abc要在一个线程中写入变量,并且要在其他线程中看到该更改则可以将Singleton bean与volatile变量一起使用。