我正在开发一个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”?我对这个话题感到困惑。
我将String abc变量设为ThreadLocal
对象,以便为每个线程提供自己的abc变量。但是我已经读过使用ThreadLocal
对象在Tomcat中发生内存泄漏。在7.0版本的Tomcat之后据说这是固定的。
因为每个线程都拥有自己的变量,并且当它们的作业完成时它们返回由container管理的线程池。但是,返回池,ThreadLocal对象不会被破坏并且它们会导致内存泄漏。
此外,String对象是不可变的,因此在理论视图中它会导致多线程问题吗?
是每个线程自己保存它们的String变量吗?例如,线程1触发然后启动方法调用,并创建单独的字符串变量“abc”和线程2触发器然后它创建新的字符串变量“abc”并且它们是否会相互损坏“abc”变量?
我真的很想知道这个使用概念并渴望学习答案。
答案 0 :(得分:5)
我会尝试单独解决您的问题。
我在bean的方法和它们的时候使用了这个变量
abc
多线程到达它会损害数据的一致性 每个帖子?
这个问题的简短回答是肯定的。如果您在一个abc
中为Thread
写了不同的值,则可能会或可能不会从另一个帖子中看到。这就是引入volatile
关键字的原因。
我想在Spring
中拥有可变单例bean,那么您需要注意同步和使用volatile
。
数据不会“损坏”,因为正如您所指出的,String
是不可变的。但是一个线程可能看不到另一个线程改变了abc
的值。
所以你有一个变量abc
;
abc
=“嗨。”abc
读为“嗨。”。abc
abc="Hello."
abc
,不清楚abc
是否显示“嗨”。或“你好。”。我将String abc变量设为ThreadLocal对象,以便为每个线程提供自己的abc变量
ThreadLocal
用于为每个线程提供不同的变量实例。这通常用于将状态绑定到Web服务器中的线程,因为Web服务器使用线程预请求模型。
Tomcat 7 没有修复ThreadLocal
泄漏问题。如果您没有从线程中删除已设置的变量,那么将导致泄漏。或者更糟糕的是,请求将从另一个请求的上下文中获取项目。当一个线程被检入到池中,并且其ThreadLocal
中有一个上下文,然后被另一个请求检出时,就会发生这种情况。
Tomcat 7轮胎检测这些问题并换出线程以删除它们的ThreadLocal
变量。这很昂贵,可以通过正确使用ThreadLocal
来避免。
您需要在servlet过滤器中清除ThreadLocal
个变量。
所以:
如果你想在一个帖子中写一个变量abc
而在其他线程中有没有看到那么你可以使用ThreadLocal
,但在每次请求后你需要非常小心地清除状态。
如果你想在一个线程中写入一个变量abc
,并且在其他线程中有看,那么你可以使用一个带有{{的单例bean 1}}变量。
答案 1 :(得分:1)
我想在你的情况下,如果你定义你的bean的范围,你的实例变量应该是Singleton
。
根据Spring reference document,下面是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.