JavaSpringbean中的实例变量

JavaSpringbean中的实例变量,java,multithreading,spring,thread-safety,heap,Java,Multithreading,Spring,Thread Safety,Heap,我正在开发一个JavaSpringMVC项目,我不知道如何在JavaSpringbean中使用实例变量 我在JavaSpringbean中使用了一个实例变量,它的类型是String private String abc = "hell"; 正如我们所知,Java Spring的默认作用域是Singleton,它们是在项目启动时构建的。它是单实例,我的实例变量必须是线程安全的 我在bean的方法中使用了这个变量“abc”,当多个线程访问它们时,它会破坏每个线程的数据一致性吗 例如,线程1到达be

我正在开发一个JavaSpringMVC项目,我不知道如何在JavaSpringbean中使用实例变量

我在JavaSpringbean中使用了一个实例变量,它的类型是String

private String abc = "hell";
正如我们所知,Java Spring的默认作用域是Singleton,它们是在项目启动时构建的。它是单实例,我的实例变量必须是线程安全的

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

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

我将字符串abc变量设置为
ThreadLocal
对象,以提供每个线程都拥有自己的abc变量。但我已经了解到,使用
ThreadLocal
对象会在Tomcat中发生内存泄漏。在7.0版Tomcat之后,据说它已经修复

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

此外,字符串对象是不可变的,所以从理论上看,它是否会导致多线程问题

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


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

我想在你的例子中,如果你将bean的范围定义为
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.

我将尝试分别回答您的问题

我在bean的方法中以及当它们 被多个线程访问是否会破坏数据的一致性 每条线

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

如果您想在
Spring
中使用mutable单例bean,那么您需要小心同步和使用
volatile

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

因此,您有一个变量
abc

  • abc
    =“您好。”
  • 线程1将
    abc
    读取为“Hi”
  • 线程1通过写入引用来更改abc
  • abc=“Hello。”
  • 线程2读取
    abc
    ,不清楚
    abc
    是读取“Hi.”还是“Hello.”
  • 我将字符串abc变量设置为ThreadLocal对象,以提供每个线程都拥有自己的abc变量

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

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

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

    您需要清除servlet过滤器中的
    ThreadLocal
    变量

    因此:

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


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

    @boristesspider不同于将单例bean定义范围限定为任意数量的对象实例的
    prototype
    Singleton
    scope将单个bean定义限定为每个springioc容器的单个对象实例。我将介绍使用作用域创建的对象实例的数量。首先感谢您的回复Vikas V。例如,线程1到达bean并将abc变量更改为“hello”。此时,线程2引用abc变量点“hell”或“hello”?我对这个主题感到困惑。@user216428因为我正在讨论bean的作用域,而且容器中只有一个bean实例,当Thread2读取abc变量时,它应该得到“hello”。@VikasV这不是真的。请看我的答案。@BoristheSpider在您写的答案中,然后您可以使用带有可变变量的单例bean,所以,bean的作用域确实起到了作用,对吗?您可以使用
    prototype
    作用域或其他具有
    volatile
    变量的作用域?请更正。我在上使用了ThreadLocal对象