一 模式定义
保证一个类只有一个实例,并提供一个全局访问点
二 场景
之所以使用单例模式,是因为某些重量级的对象,不需要多个实例,因为占用系统资源过高。例如线程池,数据库连接池。
三 两种经典模式
1.懒汉模式
只有在对象使用时才初始化。
举例代码如下:
/*** @author xionglz* @Slogan 致敬大师,致敬未来的你*/class LazySingleton{//使用valatitle防止指令重排序,不使用可能造成空指针异常。private volatile static LazySingleton instance;/*私有构造函数防止其他类创建实例*/private LazySingleton(){}public static LazySingleton getInstance() {//每次初始化前先判断是否为空if (instance==null){//使用java内置锁保证线程安全synchronized (LazySingleton.class){//双重检查防止重复创建对象保证单例,因为第二个线程拿到锁后,此时对象可能已经创建if (instance==null){/* 创建对象非原子操作JIT可能会进行指令重排,所以需用valatitle创建对象顺序为:1.分配空间2.初始化3.引用赋值*/instance=new LazySingleton();}}}return instance;}
}
2.饿汉模式
在类加载的初始化阶段就完成了实例的创建。本质上是利用了jvm的类加载机制保证实例的唯一性。
类加载过程:
只有在真正使用对应的类时才会触发初始化。例如启动类所在函数,直接进行new 操作,访问静态属性,静态方法,用反射访问一个类,初始化一个类的子类。
代码如下
class HungrySingleton{private static HungrySingleton instance = new HungrySingleton();private HungrySingleton(){//防止反射创建实例if (HungrySingleton.instance != null) {throw new RuntimeException( " 不允许多个实例。" );}}public static HungrySingleton getInstance() {return instance;}
}
四 枚举类型
1.天然不支持反射获取实例
2.通过jvm类加载机制实现