单例模式
饿汉模式
代码示例:
public class Singleton{
private static Singleton instance = new Singleton();
private Singleton(){}
public static Singleton newInstance(){
return instance;
}
}
分析
- 类的构造函数为private,保证了其他类不能实例化
Singleton
,但提供了静态方法 - 在类加载的时候就创建了实例,该实例在整个程序的生命周期中存在。
优点:jvm在进行类加载时就创建好了实例,避免了之后多线程同时调用newInstance()出现多个实例的情况(多线程同步的问题)
缺点:在这个单例还没有用到就已经在类加载之后被创建。造成了内存浪费
适用场景: 适合单例占用内存比较小,在初始化时就会被用到的情况。
javaApi中,Runtime.getRuntime() 就是典型的饿汉单例
懒汉模式
代码示例:
public class LazyMode {
private LazyMode(){}
//禁止指令重排序优化
private static volatile LazyMode lasyMode = null;
//双重校验锁
public static LazyMode getInstance(){
if (lasyMode == null ) {
synchronized (LazyMode.class) {
if (lasyMode == null) {
lasyMode = new LazyMode();
}
}
}
return lasyMode;
}
}
分析
- 懒汉模式利用延迟加载,在需要用到该实例的时候才去创建。
- 需要解决线程同步问题.
静态内部类
代码示例:
public class StaticClass {
private StaticClass(){}
private static class StaticClassBat {
private static StaticClass getInstance = new StaticClass();
}
private static StaticClass getInstance(){
return StaticClassBat.getInstance;
}
}
分析
- 利用类加载机制,初始化时会将
StaticClass
加入方法区中;StaticClassBat
内部类属于StaticClass
的私有类并不会创建到jvm堆
中。 - 当调用
getInstance()
方法时,才会去堆中生成一个StaticClass对象
这种方式可以同时保证延迟加载和线程安全。
利用枚举创建单例模式
代码示例:
public enum SingleEnum {
INSTANCE;
static class SingleEnumClass{
private static SingleEnum getInstance = SingleEnum.INSTANCE;
}
public static SingleEnum getInstance() {
return SingleEnumClass.getInstance;
}
}
分析
- 当了解Enum类后就会明白了。可以看看class字节码反编译后的文件
总结***
个人建议使用静态内部类这种实现方式,当然还是看具体的需求。