单例模式
01 Singleton Pattern 单例模式
概念
:单例的对象只能有一个实例存在实现方式
:一个类能返回对象的一个引用(永远是同一个)和一个获得该唯一实例的方法(必须是静态方法)目的
:保证系统中只有一个实例,从而在某些特定的场合下达到节约或者控制系统资源的目的适用
:当你只需要一个实例对象的时候,就可以考虑适用单例模式
如在资源共享的情况下,避免由于多个资源操作导致的性能或耗损等
02 懒汉式的单例模式
优:单例对象的生成是在应用需要使用单例对象时才去构造,可以提高应用启动速度
缺:不是线程安全,如果多个线程同时调用getInstance方法,那么可能会生成多个单例对象
适用:单例对象功能复杂,占用内存大,对应用的启动速度有要求
不适用:多线程同时使用
public class LazySingleton {
private static LazySingleton lazySingleton = null;
// 私有构造器,不让外部通过new创建对象
private LazySingleton() {}
public static LazySingleton getInstance() {
if(null == lazySingleton) {
// 当为空时,在类内部通过new关键字创建
lazySingleton = new LazySingleton();
}
return singleton;
}
}
03 饿汉式的单例模式
优:简单方便 安全可靠
缺:不管程序中是否使用到单例对象,都会生成单例对象,并由静态对象是在类加载时就需要生成,会降低应用启动速度
适用:类对象功能简单,占用内存较小,使用频繁
不适用:类对象功能复杂,占用内存大,使用概率较低
public class HungrySingleton {
// 类被加载时就创建实例
private static final hungrySingleton = new HungrySingleton();
private HungrySingleton() {}
public static HungrySingleton getInstance() {
return hungrySingletion;
}
}
04 加锁的懒汉式 线程安全
优:同懒汉式
缺:加锁后有额外消耗
public class LockSingleton {
private static LockSingleton lockSingleton = null;
private LockSingleton() {}
/* 懒汉同步锁
获取方式 添加锁对象
添加线程保护机制,确保线程安全 */
public static LockSingleton getInstance() {
// 线程同步
synchronized (LockSingleton.class) {
if(null = LockSingleton) {
lockSingleton = new LockSingleton();
}
}
return lockSingleton;
}
}
05 双重校验加锁的懒汉式#1
优:懒加载 线程安全 效率高
缺:代码较复杂
public class DoubleCheckLockSingleton {
private static DoubleCheckLockSingleton doubleCheckLockSingleton = null;
private DoubleCheckLockSingleton() {}
// 双重校验 + 锁模式
public static DoubleCheckLockSingleton() {
if(null == doubleCheckLockSingleton) {
synchronized (DoubleCheckLockSingleton.class) {
if(null == doubleCheckLockSingleton) {
doubleCheckLockSingleton = new DoubleCheckLockSingleton();
}
}
}
/* 单例模式不为空,直接返回单例
不需要判断线程同步锁和构造单例对象
减少判断线程同步锁的次数,从而提高效率 */
return doubleCheckLockSingleton();
}
}
05 双重校验加锁的懒汉式#2
public class DoubleCheckLockSingleton {
/* volatile 防止编译器自行优化代码 JVM
老版本JDK中无法正常工作 */
private volatile static DoubleCheckLockSingleton doubleCheckLockSingleton = null;
private DoubleCheckLockSingleton() {}
// 双重校验 + 锁模式
public static DoubleCheckLockSingleton() {
if(null == doubleCheckLockSingleton) {
synchronized (DoubleCheckLockSingleton.class) {
if(null == doubleCheckLockSingleton) {
doubleCheckLockSingleton = new DoubleCheckLockSingleton();
}
}
}
/* 单例模式不为空,直接返回单例
不需要判断线程同步锁和构造单例对象
减少判断线程同步锁的次数,从而提高效率 */
return doubleCheckLockSingleton();
}
}
06 内部静态类实现的懒汉式
优:实现简单,懒加载,线程安全
缺:增加了一个静态内部类,apk文件增大 why
public class InnerClassSingleton {
/* 内部静态类
Java静态内部类是使用到该静态的时候才去加载的 线程安全 */
private static class InnerClassSingletonInstance {
private static final InnerClassSingleton innerClassSingleton = new InnerClassSingleton();
}
private InnerClassSingleto() {}
/* 内部类静态获取
InnerClassSingletonInstance是私有的,除了getInstance()之外没有其他方式可以访问实例对象
当调用getInstance()方法时才会去真正的创建实例对象 */
public static InnerClassSingletonInstance getInstance() {
return InnerClassSingletonInstance.innerClassSingleton;
}
}
07 使用枚举的单例模式
优:线程安全,不用担心序列化和反射问题 防止反序列化带来的问题 why
缺:枚举占用内存多一点 why
public enum EnumSingleton {
// 通过EnumSingleton.INSTANCE来访问实例对象
INSTANCE;
private String field;
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
}