单例模式
为什么要有单例模式? 咱也不知道。。
反正单例模式的作用就是保证只创建一个对象。
1)构造函数设置为private,不然没法单例了啊 2)变量声明为静态的,类声明为静态的,这样的才能调用类的方法来创建类的实例
注意: 如果用反射,即便构造函数设置为 private,仍然可以通过反射来创建对象实例 (这里的单例指的是不考虑反射的情况)
1. 懒汉式 (哈哈,我懂了为什么叫懒汉式了,是挺懒的) 线程不安全 【怎么有点通过工厂来获取实例的感觉】
class Singleton{ private static Singleton singleton=null; private Singleton(){}; public static Singleton getInstance(){ if(singleton==null){ singleton=new Singleton(); } return singleton; } }
2. 懒汉式 线程安全 只是在方法上面加入了synchronized进行修饰 当然 synchronized也可以修饰方法中的代码段
class Singleton{ private static Singleton singleton=null; private Singleton(){}; public static synchronized Singleton getInstance(){ if(singleton==null){ singleton=new Singleton(); } return singleton; } }
3. 很明显, 方式2尽管是线程安全了,但是并发度不高,在高并发下显然不合适,所以要优化同步的位置
采用 dcl 双重检查+锁 注意singlton变量要用valotile来修饰,用来禁止指令重排
为对象分配内存空间 实例化数据 引用指向内存空间 【创建对象的三个过程】
但是如果,第三步排到了第二步的前面,那么引用已经指向内存空间,但是还没有实例化,使用对象时,会出现空指针异常错误。
(由第一个 if 判断导致的,不是第二个 if 判断导致的!!!)
class Singleton{ private static volatile Singleton singleton=null; private Singleton(){}; public static Singleton getInstance(){ if(singleton==null){ synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }
4. 静态内部类
class Singleton{ private Singleton(){}; public static Singleton getInstance(){ return SingletonHolder.singleton; } static class SingletonHolder{ private static final Singleton singleton=new Singleton(); } }
5. 饿汉式 因为是类变量,所以这里在类加载的时候就行了初始化,不是使用的时候进行的初始化,也就不是懒加载(使用的时候才会创建)
【有种Spring中的单例和原型之间的感觉】
class Singleton{ private static final Singleton singleton=new Singleton(); private Singleton(){}; public static Singleton getInstance(){ return singleton; } }
6. 枚举 (这个我也是刚知道。。。学习了,有收获)
(能够防止 反序列化 和 反射 导致破坏单例模式的问题)
enum EnumSingleton{ singleton; void show(){ System.out.println("其实不是很难啊!!!"); } }
直接就能用了!!!!
public static void main(String[] args) { EnumSingleton.singleton.show(); }
参考文档:
各种单例实现方式: https://www.cnblogs.com/happy4java/p/11206105.html
枚举类的安全性: https://blog.csdn.net/whgtheone/article/details/82990139
浙公网安备 33010602011771号