Java 使用Spring的服务器内存上的单个类文件导致问题
我不太知道如何解释这种情况,我会尽量弄清楚 我目前正在编写一个web应用程序,使用Spring来管理bean。显然,不止一个人会使用这个应用程序。每个用户都有一组与自己相关的数据。我的问题来自我刚进入开发领域时介绍的一些糟糕的设计。情况如下:Java 使用Spring的服务器内存上的单个类文件导致问题,java,spring,spring-mvc,design-patterns,Java,Spring,Spring Mvc,Design Patterns,我不太知道如何解释这种情况,我会尽量弄清楚 我目前正在编写一个web应用程序,使用Spring来管理bean。显然,不止一个人会使用这个应用程序。每个用户都有一组与自己相关的数据。我的问题来自我刚进入开发领域时介绍的一些糟糕的设计。情况如下: @Component public class ServiceClass implements IService { @Autowired private Dependency firstDependency; @Autowired priv
@Component
public class ServiceClass implements IService {
@Autowired
private Dependency firstDependency;
@Autowired
private UsefulObject secondDependency;
private DataSet dataSet; // THIS LINE IS IMPORTANT
public void entryPoint(String arg1, int arg2, Structure arg3) {
/* Query data from a database specific from the project (not SQL
oriented. I absolutely need this information to keep going. */
dataSet = gatherDataSet(String ar1);
/* Treat the data */
subMethodOne(arg1);
subMethodTwo(arg2);
subMethodThree(arg3);
}
private subMethodOne(String arg1) {
// Do some things with arg1, whatever
subSubMethod(arg1);
}
private subSubMethod(String arg1) {
/* Use the DataSet previously gathered */
dataSet.whateverDoing();
}
... // Functions calling sub-methods, using the DataSet;
由于每个用户都有一个不同的数据集
,所以我认为最好在每次调用我的服务时调用它。同样,由于它在调用层次结构中使用得非常深入,我认为将其存储为属性是一个好主意
我遇到的问题是,当两个用户几乎同时使用此服务时,我会遇到交叉数据问题。发生以下情况:
- 第一个用户进来,调用
gatherDataSet
- 第二个用户进来,调用
。第一个用户仍然在治疗李>gatherDataSet
- 第一个用户仍然使用被第二个用户覆盖的
对象数据集
- 是否存在避免此类行为的设计模式/方法
- 您是否可以配置Spring,使其使用两个用户的两个实例(以此类推),以避免此问题
奖励:(有点不相关)如何实现一个非常大的数据映射器?最简单的解决方案就是将
数据集
存储在类字段中
相反,将数据集
存储在局部变量中,并将其作为参数传递给其他函数,这样就不会出现任何并发问题,因为每个调用堆栈都有自己的实例
例如:
public void entryPoint(String arg1, int arg2, Structure arg3) {
// Store the dataset in a local variable, avoiding concurrency problems
Dataset dataSet = gatherDataSet(String ar1);
// Treat the data passing dataset as an argument
subMethodOne(arg1, dataset);
subMethodTwo(arg2, dataset);
subMethodThree(arg3, dataset);
}
最简单的解决方案是不将
数据集
存储在类字段中
相反,将数据集
存储在局部变量中,并将其作为参数传递给其他函数,这样就不会出现任何并发问题,因为每个调用堆栈都有自己的实例
例如:
public void entryPoint(String arg1, int arg2, Structure arg3) {
// Store the dataset in a local variable, avoiding concurrency problems
Dataset dataSet = gatherDataSet(String ar1);
// Treat the data passing dataset as an argument
subMethodOne(arg1, dataset);
subMethodTwo(arg2, dataset);
subMethodThree(arg3, dataset);
}
对其使用同步修改器。 As“同步在多个线程倾向于共享相同资源的应用程序中起着关键作用,特别是当这些资源必须保持某种敏感状态时,多个线程同时执行的操作可能导致资源处于不一致的状态。”
对其使用同步修改器。 As“同步在多个线程倾向于共享相同资源的应用程序中起着关键作用,特别是当这些资源必须保持某种敏感状态时,多个线程同时执行的操作可能导致资源处于不一致的状态。” 对象成员变量(字段)与对象一起存储在堆上。因此,如果两个线程在同一个对象实例上调用一个方法,并且该方法更新对象成员变量,则该方法不是线程安全的 但是,如果资源是在同一线程的控制下创建、使用和释放的,并且从未逃脱该线程的控制,则该资源的使用是线程安全的 记住这一点,改变你的设计。这是一本必须阅读的书,有助于提出好的基于java的软件设计 更多stackoverflow链接: Spring促进了单例模式和(它是默认的bean范围)。为两个不同用户配置两个服务类对象的Spring配置称为prototype bean作用域,但应尽可能避免 考虑使用内存映射或外部无sql数据存储或外部关系数据库,对象成员变量(字段)与对象一起存储在堆中。因此,如果两个线程在同一个对象实例上调用一个方法,并且该方法更新对象成员变量,则该方法不是线程安全的 但是,如果资源是在同一线程的控制下创建、使用和释放的,并且从未逃脱该线程的控制,则该资源的使用是线程安全的 记住这一点,改变你的设计。这是一本必须阅读的书,有助于提出好的基于java的软件设计 更多stackoverflow链接: Spring促进了单例模式和(它是默认的bean范围)。为两个不同用户配置两个服务类对象的Spring配置称为prototype bean作用域,但应尽可能避免 考虑使用内存映射或外部无sql数据存储或外部关系数据库 您是否可以配置Spring,使其使用两个用户的两个实例(以此类推),以避免此问题 您已经正确地提到,您做出的设计决策是有缺陷的。但要回答您的特定问题,即哪些应该让您的用例正确工作,但对性能成本有影响: 您可以将Springbean设置为不同的作用域(与您的用例:原型/请求或会话相关),当Springbean被实例化时,这些作用域将被修改。默认行为是每个spring容器一个bean(singleton),因此存在并发问题。看 您是否可以配置Spring,使其使用两个用户的两个实例(以此类推),以避免此问题 您已经正确地提到,您做出的设计决策是有缺陷的。但要回答您的特定问题,即哪些应该让您的用例正确工作,但对性能成本有影响: 您可以将Springbean设置为不同的作用域(与您的用例:原型/请求或会话相关),当Springbean被实例化时,这些作用域将被修改。默认行为是每个spring容器一个bean(sing)