概念:
单例:保证一个类,只有一个实例,并且提供一个访问该实例的全局访问地。
常见应用场景
优缺点:
单例只是只生成一个实例,减少系统性能开销
实现方式:
主要:
饿汉模式(线程安全,调用效率高,不能延时加载)
懒汉模式(线程安全,调用效率不高,延时加载)
其他
双重检测琐式(由于JVM底层内部模型原因,偶尔会出现问题,不建议使用)
静态内部类式(线程安全,调用效率高,可以延时加载)
枚举单列(线程安全,调用效率高,不能延时加载)
1.饿汉式实现
优缺点:
当类被加载时就被被创建,如果没有调用getInstance 时,这个类就不会被用到,造成资源浪费
创建步骤:
1.私有构造 2.静态私有变量 2.公有静态方法
public class Demo1 {
private static Demo1 demo1 = new Demo1();
private Demo1(){
}
public static Demo1 getInstance(){
return demo1;
}
}
Demo1 demo1 = Demo1.getInstance();
2.懒汉式实现
优缺点:
资源利用效率高,但是每次调用getInstance() 方法都要同步,效率较低
创建步骤:
1.私有构造 2.私有静态变量 2.公司有静态方法
public class Demo {
private static Demo demo;
private Demo(){
}
public synchronized static Demo getInstance(){
if (demo == null){
demo = new Demo();
}
return demo;
}
3.双重检测琐式(一般不用)
4.静态内部类的实现(懒加载)
要点:
外部没有staitc 属性,则不会像饿汉式那样立即加载对象
只有真正调用getInstance() 才会加载静态内部类,加载类时线程安全的。instance是static final 类型,保证了内存中只有这样一个实例存在,而且只能被赋值一次,从而保证了线程安全性。兼备了并发高效调用和延迟加载的优势。
public class Demo2 {
private static class SignalClass{
private static final Demo2 demo2 = new Demo2();
}
public static Demo2 getInstance(){
return SignalClass.demo2;
}
private Demo2(){
}
}
5.枚举实现方式
优点:
实现简单
枚举本身就是单列模式,有JVM从根本上提供保障,避免通过反射和反序列化的漏洞
缺点:
无延迟加载
public enum Demo3 {
INSTANCE; //这个枚举元素,本身就是单列对象
}
注意:反射可以破解上面几种实现的方式,枚举不可以