作为23中设计模式之一—单例模式。是我们最耳熟能详的一种设计模式,也是被广大coder所掌握的一种设计模式,但是你真的掌握了单例模式吗?能保证没有bug吗? Java中单例模式是一种广泛使用的设计模式。单例模式的主要作用是保证在Java程序中,某个类只有一个实例存在。一些管理器和控制器常被设计成单例模式。 单例模式有很多好处,它能够避免实例对象的重复创建,不仅可以减少每次创建对象的时间开销,还可以节约内存空间(比如spring管理的无状态bean);能够避免由于操作多个实例导致的逻辑错误。如果一个对象有可能贯穿整个应用程序,而且起到了全局统一管理控制的作用**,那么单例模式也许是一个值得考虑的选择。 单例模式有很多种写法(7种),大部分写法都或多或少有一些不足。下面将分别对这几种写法进行介绍。
1、懒汉(线程不安全):
public class Singleton {
private static Singleton instance;
private Singleton (){} //私有构造函数
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
这种写法lazy loading(懒加载)很明显,但是一看就知道,存在线程安全问题,不解释 禁止这样书写。
2、懒汉(线程安全):
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
显然加了个synchronized来保证线程安全,but,效率太低了,毕竟99.99%的情况下是不需要同步的,有点用力过猛 3、饿汉
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
这种基于classloder机制避免了多线程的同步问题,初始化的时候就给装载了。但是现在,没有懒加载的效果了 4、饿汉(变种):
public class Singleton {
private static Singleton instance = null;
static {
instance = new Singleton();
}
private Singleton (){}
public static Singleton getInstance() {
return this.instance;
}
}
第三种方式差不多,都是在类初始化即实例化instance。 5、静态内部类:
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
第三种和第四种方式是只要Singleton类被装载了,那么instance就会被实例化(没有达到lazy loading效果),而这种方式是Singleton类被装载了,instance不一定被初始化。因为SingletonHolder类没有被主动使用,只有显示通过调用getInstance方法时,才会显示装载SingletonHolder类,从而实例化instance。这个时候,这种方式相比第三和第四种方式就显得很合理。 6、双重校验锁(这个相对来说比较复杂):
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
使用到了volatile机制。这个是第二种方式的升级版,俗称双重检查锁定。既保证了效率,又保证了安全。 7、枚举:
public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}
这种方式是Effective Java作者Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象,可谓是很坚强的壁垒啊。所以这种写法,其实是十分推荐的
到处都是
本文总结了7种Java中实现单例的方法,其中前两种都不够完美,双重校验锁和静态内部类的方式可以解决大部分问题,平时工作中使用的最多的也是这两种方式。所以,个人推荐枚举的方式,哈哈哈哈