Java中的这个单例类可以接受吗?
我使用了已出版的关于单例创建的教程中的概念,但希望得到一些反馈。有没有更好的方法Java中的这个单例类可以接受吗?,java,design-patterns,singleton,Java,Design Patterns,Singleton,我使用了已出版的关于单例创建的教程中的概念,但希望得到一些反馈。有没有更好的方法 public class MyDoubleLockSingleton { private volatile static Object _mySingleton; //private constructor private MyDoubleLockSingleton() { if (_mySingleton == null) { MyDoubleLockS
public class MyDoubleLockSingleton {
private volatile static Object _mySingleton;
//private constructor
private MyDoubleLockSingleton() {
if (_mySingleton == null) {
MyDoubleLockSingleton.getSingleton();
}
}
// double lock singleton approach
public static Object getSingleton() {
synchronized (MyDoubleLockSingleton.class) {
if (_mySingleton == null) {
_mySingleton = new Object();
}
return (Object)_mySingleton;
}
}
}
除了像Vince提到的那样进行同步之外,在get singleton中返回对象也是很好的。通常在单例中,方法称为instance或getInstance。移除构造函数的主体。可以使用单例模式,但若可以,请尽量避免使用单例模式,否则在应用程序只有一个线程时,请尽可能快地初始化它。一般规则-单身汉越少越好。参见本文 从文章看区别
class SomeClass {
private Resource resource = null;
public Resource getResource() {
if (resource == null) {
synchronized {
if (resource == null)
resource = new Resource();
}
}
return resource;
}
}
class A {
static private A a = null;
public Resource instance() {
if ( a == null ) {
synchronized {
if (a == null )
a= new A();
}
}
return a;
}
}
实际上,有一种首选方法,也是最容易实现的方法枚举
- 它们保证在JVM中只有一个实例
- 它们可以安全地序列化
- 它们是线程安全的
- 它看起来更像这样:
public class MyDoubleLockSingleton {
private static final Object _lock = new Object(); // synchronize on this instead of MyDoubleLockSingleton.class
private volatile static MyDoubleLockSingleton _mySingleton;
//private constructor
private MyDoubleLockSingleton() {
// perform expensive initialization here.
}
// double lock singleton approach
public static MyDoubleLockSingleton getSingleton() {
if (_mySingleton == null) {
synchronized (_lock) {
if (_mySingleton == null) {
_mySingleton = new Object();
}
}
}
return _mySingleton;
}
}
public class MyDoubleLockSingleton {
private static final MyDoubleLockSingleton _mySingleton = new MyDoubleLockSingleton();
//private constructor
private MyDoubleLockSingleton() {
// perform initialization here.
}
// double lock singleton approach
public static Object getSingleton() {
return _mySingleton;
}
}
- 私有构造函数是执行昂贵初始化的地方
- 您最好在私人成员上同步
- 您可能希望在同步块之外添加空检查,以提高性能。否则,这种模式就没有什么意义了
public class MyDoubleLockSingleton {
private static final Object _lock = new Object(); // synchronize on this instead of MyDoubleLockSingleton.class
private volatile static MyDoubleLockSingleton _mySingleton;
//private constructor
private MyDoubleLockSingleton() {
// perform expensive initialization here.
}
// double lock singleton approach
public static MyDoubleLockSingleton getSingleton() {
if (_mySingleton == null) {
synchronized (_lock) {
if (_mySingleton == null) {
_mySingleton = new Object();
}
}
}
return _mySingleton;
}
}
public class MyDoubleLockSingleton {
private static final MyDoubleLockSingleton _mySingleton = new MyDoubleLockSingleton();
//private constructor
private MyDoubleLockSingleton() {
// perform initialization here.
}
// double lock singleton approach
public static Object getSingleton() {
return _mySingleton;
}
}
您最大的缺陷是在每次调用
getSingleton()
时同步
“双重检查”锁定的思想是首先执行非同步检查。这适用于单例已初始化的情况如果单例已经存在,则没有理由进行同步
如果在执行非同步检查时单例为null
,则同步:
public Singleton getSingleton() {
if(singleton == null) {
synchronized(lock) {
}
}
}
现在,我们需要确保从离开null检查到进入synchronized块期间,没有其他线程初始化了singleton。如果单例是在那个时候创建的,我们不想创建一个新的单例。这就是我们执行第二次空检查的原因:
public Singleton getSingleton() {
if(singleton == null) {
synchronized(lock) {
if(singleton == null) {
//create
}
}
}
}
避免这种情况的更简单方法是使用按需初始化习惯用法:
class Singleton {
private static final Singleton SINGLETON = new Singleton();
public static Singleton getSingleton() {
return SINGLETON;
}
}
其想法是让处理静态初始化(已经同步)的机制为您处理创建
更简单的替代方法是枚举
:
public enum Singleton {
INSTANCE;
}
为了减少冗长,我通常使用
GET
而不是INSTANCE
。这是假设您没有使用静态导入,如果是这样的话,您应该使用更合适的名称。您没有提到您的java版本,但这是我过去使用的。我有一些代码应该是类似于使用单次检查锁定的单例代码,当报表线程相互冲突时,在负载下会混淆报表。我使用了这个解决方案,名为:按需初始化持有者类习惯用法:
public class Singleton {
// Private constructor. Prevents instantiation from other classes.
private Singleton() { }
/**
* Initializes singleton.
*
* {@link SingletonHolder} is loaded on the first execution of {@link Singleton#getInstance()} or the first access to
* {@link SingletonHolder#INSTANCE}, not before.
*/
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
它有效地创建了一个线程安全的单例。同步之前,需要执行空检查。这就是“双重检查”部分的来源。首先检查,然后同步,然后再次检查以确保它仍然为空。现在,每次访问singleton时都需要同步,这会影响性能。我强烈建议使用Josh Bloch的习惯用法:按需初始化,或者首先使用
enum
:难道getInstance():Object
不是标准吗?第二:通常getInstance()
调用私有构造函数,而不是相反的方法?另外,StackOverflow不用于对代码进行反馈。它是针对特定编程问题的。为了让您的代码得到审查,请在@VinceEmigh上发布他这样做了,但是在构造函数中。这和你说的是一样的,但我想他忘了写,否则就回来了\u mySingleton代码>可能重复的