单例模式常常会是咱们学习设计模式的第一个模式。在spring框架下,Bean的默认初始化也是单例模式。 单例模式常见的有懒汉模式和饿汉模式。 先来讲说这两个命名由来。 懒汉模式: lazily 饿汉模式: early 感受是音译。。。java
通常状况下,单例对象应该是无状态的,也就是说没有成员变量字段,或者说成员变量不发生变化。 而有状态的对象,每每在系统中是多例存在。不一样的实例拥有不一样的状态。spring
public class Singleton{
private final static Singleton INSTANCE = new Singleton();
private Singleton(){}
public static getInstance(){
return INSTANCE;
}
}
复制代码
优势: 线程安全,实现简单,容易理解。 缺点: 空间浪费。在启动的时候就会建立实例。设计模式
public class Singleton {
private static Singleton INSTANCE;
static {
INSTANCE = new Singleton();
}
private Singleton(){}
public static Singleton getInstance() {
return INSTANCE;
}
}
复制代码
这种方式和第一种没有区别。安全
public class Singleton {
private static Singleton INSTANCE;
private Singleton(){}
public static Singleton getInstance(){
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
复制代码
这种方式实现了懒加载,在调用实例对象的时候才构造。可是带来的问题是线程不安全。若是是在多线程环境下,会生成多个实例。多线程
public class Singleton {
private static Singleton INSTANCE;
private Singleton(){}
public static synchronized Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
复制代码
要解决线程安全问题,最简单的作法是让方法加个同步。这样一来即可保证线程安全,可是带来的问题是性能损耗。由于其实只有在第一次构造的时候须要同步,之后获取的时候不须要同步的。框架
public class Singleton {
private static Singleton INSTANCE;
private Singleton(){}
public static Singleton getInstance() {
if (INSTANCE != null) {
return INSTANCE;
}
synchronized (Singleton.class) {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
}
return INSTANCE;
}
}
复制代码
这种方式就比较完美了。作一个双重检查,保证了在第一次构造实例的时候的线程安全。同时也保证了以后获取实例对象不须要同步。性能
public class Singleton {
private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton(){}
public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}
复制代码
这种方式表面上看和饿汉模式很类似,可是其实也是实现了懒加载。巧妙之处在于利用了内部类启动机制保证了线程安全。我的比较推荐以上两种写法。学习
public enum Singleton {
INSTANCE;
}
复制代码
坊间还有使用枚举类来实现的例子,虽然也能达到单例的效果,同时也是线程安全。可是我的并不推崇这种用法,缘由在于枚举并非设计来实现单例的,理解起来会让人困惑。spa