4

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

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

private String abc = "hell";

众所周知,Java Spring 默认作用域是 Singleton,它们是在项目启动时构建的。.它是单实例,我的实例变量必须是线程安全的。

我在bean的方法中使用了这个变量“abc”,当多个线程到达它们时会破坏每个线程的数据一致性吗?

例如,线程 1 到达 bean 并将 abc 变量更改为“hello”。此时,线程 1 引用 abc 变量指向“hell”或“hello”?我对这个话题感到困惑。

我将字符串 abc 变量设置为ThreadLocal对象,以提供每个线程都保存自己的 abc 变量。但我读过在 Tomcat 中使用ThreadLocal对象会发生内存泄漏。在 7.0 版本的 Tomcat 之后,据说它是固定的。

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

此外,String 对象是不可变的,所以在理论上它会导致多线程问题吗?

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

我真的很想知道这个用法的概念,并渴望了解答案。

4

2 回答 2

5

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

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

这个问题的简短回答是肯定的。如果您为abcin one编写了不同的值,Thread可能会或可能不会从另一个线程中看到。这就是volatile引入关键字的原因。

如果你想拥有可变的单例 bean,Spring那么你需要小心同步和使用volatile.

数据不会被“损坏”,因为正如您所指出的,String它是不可变的。但是一个线程可能看不到另一个线程改变了abc.

所以你有一个变量abc

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

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

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

Tomcat 7修复ThreadLocal泄漏问题。如果您不从线程中删除您设置的变量,那么它将导致泄漏。或者更糟糕的是,一个请求会从另一个请求的上下文中获取项目。当一个线程被签入池中并留下上下文ThreadLocal,然后被另一个请求签出时,就会发生这种情况。

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

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

所以:

如果您abc想在一个线程中写入一个变量,并且该更改不会在其他线程中看到,那么您可以使用 a ThreadLocal,但您需要非常小心地在每次请求后清除状态。

如果您abc想在一个线程中写入一个变量并且要在其他线程中看到该更改,那么您可以使用带有volatile变量的单例 bean。

于 2013-08-04T11:35:43.210 回答
2

我想在你的情况下,如果你定义你的 bean 的范围,Singleton它应该有你的实例变量。

根据Spring 参考文档,下面是 Singleton 范围 bean 的定义。

To put it another way, when you define a bean definition and it is scoped as a singleton, 
the Spring IoC container creates exactly one instance of the object defined by that bean 
definition. This single instance is stored in a cache of such singleton beans, and all 
subsequent requests and references for that named bean return the cached object.

Singleton是如果您不指定,您的 bean 将被放入的默认范围。

此外,如果您尝试使用 Spring 的 bean 范围方法处理您的案例,则应牢记以下语句。

This approach is powerful and flexible in that you can choose the scope of the objects  
you create through configuration instead of having to bake in the scope of an object at    
the Java class level.
于 2013-08-04T11:28:31.843 回答