如何在生产代码中考虑单例?
How to consider singleton in production code?
我有一些 java classes,其中成员变量都是 Autowired
使用 Spring bean。我认为这保证了单例模式。但我想知道生产服务器上的代码 运行 是怎样的?单例是保证每个线程还是全局保证?我应该如何看待开发中的并发。
编辑
一个例子:
A class 接受请求并响应它收到的请求数。
在这种情况下我们需要保证计数器的全局单例,对吗?比如说无论我们使用多少台服务器,应该只有一个计数器。这个保证是隐含的吗?
classic 单例和 Spring 单例的范围
Singleton 通常表示 JVM 上整个应用程序 运行 的单例。
Java classic 实现就是这种情况,你自己实现它(单例双重检查惯用语、枚举惯用语、initialization-on-demand 持有人惯用语等等)。
在这些情况下,单例确实是在 class 加载单例 class 时创建的,因此由 JVM 单次创建。
Spring 单例的工作方式略有不同。
他们确实依赖于容器。所以,如果你在同一个 JVM 中创建多个容器,你可能会创建多个单例。现在它真的是一个极端情况,而且这些单例 bean 之间是隔离的。所以不要关注它。
关于并发
单例没有任何并发问题,因为它们是不可变的。
当然,你可以在单例中定义依赖和属性。
但是这些在单例实例化之后不应该改变。
事实上,如果一个单例提供了允许改变其状态的方法,那么对于操作它的不同线程,您一定会遇到竞争条件。
所以作为提示,保持你的单例不可变或尽可能不可变。
如果这些不能完全不可变,则必须确保通过同步需要的 methods/fields 来处理竞争条件。
我有一些 java classes,其中成员变量都是 Autowired
使用 Spring bean。我认为这保证了单例模式。但我想知道生产服务器上的代码 运行 是怎样的?单例是保证每个线程还是全局保证?我应该如何看待开发中的并发。
编辑
一个例子: A class 接受请求并响应它收到的请求数。 在这种情况下我们需要保证计数器的全局单例,对吗?比如说无论我们使用多少台服务器,应该只有一个计数器。这个保证是隐含的吗?
classic 单例和 Spring 单例的范围
Singleton 通常表示 JVM 上整个应用程序 运行 的单例。
Java classic 实现就是这种情况,你自己实现它(单例双重检查惯用语、枚举惯用语、initialization-on-demand 持有人惯用语等等)。
在这些情况下,单例确实是在 class 加载单例 class 时创建的,因此由 JVM 单次创建。
Spring 单例的工作方式略有不同。
他们确实依赖于容器。所以,如果你在同一个 JVM 中创建多个容器,你可能会创建多个单例。现在它真的是一个极端情况,而且这些单例 bean 之间是隔离的。所以不要关注它。
关于并发
单例没有任何并发问题,因为它们是不可变的。
当然,你可以在单例中定义依赖和属性。
但是这些在单例实例化之后不应该改变。
事实上,如果一个单例提供了允许改变其状态的方法,那么对于操作它的不同线程,您一定会遇到竞争条件。
所以作为提示,保持你的单例不可变或尽可能不可变。
如果这些不能完全不可变,则必须确保通过同步需要的 methods/fields 来处理竞争条件。