单例模式的6种实现方式
单例模式是 Java 中最简单,也是最基础,最常用的设计模式之一。
通过单例模式的方法创建的类在当前进程中只有一个实例。在类内部创建自己的实例,并对外提供一个返回其单例对象的方法。单例模式的实现方式有懒汉式、饿汉式和枚举等。
饿汉式:
特点:类加载到内存后,就实例化出一个单例,JVM保证线程安全,简单实用;
缺点:不论用与不用,类加载时都会进行实例化,浪费内存空间;
静态变量:
public class Singleton { private static final Singleton INSTANCE = new Singleton(); private Singleton() { } public static Singleton getInstance() { return INSTANCE; } }
静态代码块:
和第一种方式类似;
public class Singleton { private static final Singleton INSTANCE; //静态代码块 static { INSTANCE = new Singleton(); } private Singleton() { } public static Singleton getInstance() { return INSTANCE; } }
懒汉式
特点:用的时候,检查是否有无实例,有则返回,没有则进行实例化;
缺点:为保证线程安全,需要加上synchronized关键字,会影响程序执行效率;
方法上加synchronized
public class SingleLazy { private static SingleLazy INSTANCE; private SingleLazy() { } public synchronized static SingleLazy getInstance() { if (INSTANCE == null) { INSTANCE = new SingleLazy(); } return INSTANCE; } }
双检锁:
将synchronized加在对象上,提高执行效率,需要加上双重校验;
public class SingleLazy { private static volatile SingleLazy INSTANCE; private SingleLazy() { } public static SingleLazy getInstance() { if (INSTANCE == null) { synchronized (SingleLazy.class) { //加上双重校验 if (INSTANCE == null) { INSTANCE = new SingleLazy(); } } } return INSTANCE; } }
静态内部类方式:
特点:加载外部类时不加载内部类,实现懒加载,由JVM保证单例;
public class SingleLazyInner { private SingleLazyInner() { } private static class SingleManager { private static final SingleLazyInner INSTANCE = new SingleLazyInner(); } public static SingleLazyInner getInstance() { return SingleManager.INSTANCE; } }
枚举式
枚举
特点:保证线程安全,而且可以防止反序列化;
public enum SingleEnum { INSTANCE; }
总结:
懒汉式最为简单实用且线程安全;静态内部类方式实现了懒加载,比懒汉式更节省空间;饿汉式如果不加锁无法保证线程安全,如果加锁会一定程度上影响效率,较为复杂;枚举式比较简洁,且防止反序列化,设计上最完美。