如何选用哪种方式实现单例模式?
一般情况下,不建议懒汉式,建议使用饿汉式;只有在要明确实现延迟加载效果时,才会使用静态内部类;如果涉及到反序列化创建对象时,可以尝试使用枚举;如果有其他特殊的需求,可以考虑使用双重检查锁。
- 3.1 饿汉式
- 3.2 懒汉式
- 3.3 double-checked locking(双重检查锁)
- 3.4 静态内部类
- 3.5 枚举
延迟加载
线程安全
调用效率
饿汉模式
1 public class Singleton {2 /*3 * 利用静态变量来记录Singleton的唯一实例4 * 直接初始化静态变量,这样就可以确保线程安全了5 */6 private static Singleton uniqueInstance = new Singleton();78 /*9 * 构造器私有化,只有Singleton类内才可以调用构造器10 */11 private Singleton(){1213 }1415 public static Singleton getInstance(){16 return uniqueInstance;17 }1819 }
懒汉模式
public class SingletonDemoInLazy {// 私有实例,初始化的时候不加载(延迟加载)private static SingletonDemoInLazy instance;// 私有构造private SingletonDemoInLazy() {}// 公共获取实例方法(线程不安全)public static SingletonDemoInLazy getInstance() {if(instance == null ) { // 使用的时候加载instance = new SingletonDemoInLazy();}return instance;}}
懒汉的双重加锁机制
1 public class Singleton {2 /*3 * 利用静态变量来记录Singleton的唯一实例4 * volatile 关键字确保:当uniqueInstance变量被初始化成Singleton实例时,5 * 多个线程正确地处理uniqueInstance变量6 *7 */8 private volatile static Singleton uniqueInstance;910 /*11 * 构造器私有化,只有Singleton类内才可以调用构造器12 */13 private Singleton(){1415 }1617 /*18 *19 * 检查实例,如果不存在,就进入同步区域20 */21 public static Singleton getInstance(){22 if(uniqueInstance == null){23 synchronized(Singleton.class){ //进入同步区域24 if(uniqueInstance == null){ //在检查一次,如果为null,则创建25 uniqueInstance = new Singleton();26 }27 }28 }2930 return uniqueInstance;31 }3233 }
静态内部类
public class Singleton {private static class LazyHolder {private static final Singleton INSTANCE = new Singleton();}private Singleton (){}public static final Singleton getInstance() {return LazyHolder.INSTANCE;}}
枚举模式
public enum Singleton {INSTANCE;public void doSomething() {System.out.println("doSomething");}}调用方法:public class Main {public static void main(String[] args) {Singleton.INSTANCE.doSomething();}}直接通过Singleton.INSTANCE.doSomething()的方式调用即可。方便、简洁又安全。
单元素的枚举类型已经成为实现Singleton的最佳方法
