【问题标题】:Singleton class or instance in javajava中的单例类或实例
【发布时间】:2015-02-18 23:28:55
【问题描述】:

我了解在Spring框架中,bean的默认作用域是Singleton。这意味着每个容器只创建一个 bean 实例。

但我实际上无法理解以下场景。

例如类,假设类“SingleTonClass”在spring context.xml中配置为单例bean, 1)每次有这个类的请求,它是否使用相同的实例。如果是,那么如果我从另一个班级和new SingleTonClass().sum(5,6) 拨打类似new SingleTonClass().sum(3,4) 的电话,会给我正确的结果还是有时会出现问题?

2) 如果所有请求都使用同一个实例,那么在幕后怎么可能所有请求都使用一个实例?如果对同一个单例类有 100 个请求,每个请求都必须等到上一个请求完成?

编辑:

假设我使用的是 @Autowired 而不是 new 运算符

在我的主课中,我正在尝试使用使用 spring 配置的 bean。假设 MyMain 是否被多次调用(可能是并发调用,也可能不是并发调用),我想了解上面帖子中的第 2 点(编辑)

public class MyMain() {

@Autowired
SingleTonClass singleTonClass;

}




   public class SingleTonClass {

    private int a=0;
    private int b=0;

    public int sum(int a ,int b) {

    return a+b;
    }
  }

【问题讨论】:

  • 实际上,这个具体的例子看起来对于静态方法来说会更好,而不是单例类。但是,我很确定这是因为您从不使用构造函数,只使用像 SingletonClass.getInstance() 这样的方法,它返回单例。
  • 我想当你在框架中配置一个bean为单例时,你需要从Application上下文中获取实例,否则它只是另一个具有多个实例的类。
  • btw.- 这是单件,不是单件。单吨为 1000 公斤。
  • 如果您使用new,您将绕过 Spring,并且您获得的实例将是每次调用的新实例。但是,在您的特定示例中,该方法是无状态的,因此无论如何它对结果没有任何影响。

标签: java spring


【解决方案1】:

1) 如果您依赖 Spring 来管理您的 bean,并且正如您所说的使用默认的单例范围,那么其他 bean 将使用相同的实例。但是,如果您自己实例化该类(例如使用new),那么每次都会有您的类的一个新实例。

2) 如果您有 100 个并发请求,那么将有 100 个线程,并且所有线程都可以同时调用您的类而不会阻塞。也就是说,您可以使线程相互等待(例如,使用synchronized 或任何Lock 类)。自然,性能会受到影响,因为您现在有 99 个线程正在等待。您更喜欢这种解决方案的唯一原因是您的 bean 是否具有共享的、可变的状态,我不建议这样做。按照这些思路,您可以从示例中删除实例变量 ab。毕竟,它们并没有被使用,因为 ab 都是作为方法参数传递的:

public class SingleTonClass {

    public int sum(int a ,int b) {
        return a+b;
    }
}

【讨论】:

    【解决方案2】:

    当您执行new SingleTonClass() 时,您将始终获得该课程的新副本。要使用 Spring 实例化功能,您需要让 Spring 为您进行配置,例如使用 @Autowired 注释。

    至于多个请求同时命中单个实例的问题,您必须使您的类无状态或线程安全。这是一个无法简单回答的话题,但可以开始here.

    【讨论】:

    • 感谢 user3120173。您的大部分回复对我都有帮助,但我只能接受一个。
    【解决方案3】:

    您需要编写无状态 bean(意味着 bean 中不应有任何数据存储),以免担心线程安全。或者你需要自己处理线程安全。 Spring 默认创建一个类的单例非线程安全实例。甚至“原型”范围也不是线程安全的。当您将作用域定义为原型时,这只是意味着 spring 每次在另一个组件中注入时都会创建一个新实例,而不是每次执行这些组件时都会创建一个实例。

    例如,A 类注入两个组件,即 bean a1 和 a2。 SpringContext 中只有两个实例,即使这些组件处理了数百万个请求。

    请参阅此question,了解有关您可以遵循的不同设计策略的更多信息。

    顺便说一句,在您的示例中,我认为在类级别不需要 private int a, b 声明。事实上,它甚至没有被使用,因此这个 bean 是线程安全的。

    【讨论】:

      猜你喜欢
      • 2023-03-08
      • 2013-07-17
      • 2011-06-10
      • 1970-01-01
      • 1970-01-01
      • 2021-02-13
      • 2014-06-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多