一、概念
单例模式中对象创建只有一个单独的实例,只有唯一的全局访问点。也可以说单例就是保证一个类只有一个实例。
二、实现方法
单例模式的实现方法有很多,在这里介绍几种常用或者说常见的:
1、懒汉式
01 02 03 04 05 06 07 08 09 10 11 | class LazySingleton{ private static LazySingleton singleton; private LazySingleton(){ } public static LazySingleton getInstance(){ if(singleton==null){ singleton=new LazySingleton(); } return singleton; } } |
从代码中也可以看出,懒汉就是每次使用时才进行实例化,这也算是其一个优点, 而缺点也显而易见,即其时线程不安全的,在多线程下不能正常工作。
2、饿汉式
1 2 3 4 5 6 7 | class HungrySingleton{ private static HungrySingleton singleton=new HungrySingleton(); private HungrySingleton(){} public static HungrySingleton getInstance(){ return singleton; } } |
饿汉式单例模式相比于懒汉式单例,在静态初始化时完成单例对象的实例化。缺点在于不管是否使用这个单例,它都会一直在内存中,优点是其是线程安全的单例模式。
3、双重校验锁单例模式
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 | class LockSingleton{ private volatile static LockSingleton singleton; private LockSingleton(){}
public static LockSingleton getInstance(){ if(singleton==null){ synchronized(LockSingleton.class){ if(singleton==null){ singleton=new LockSingleton(); } } } return singleton; } } |
双重校验锁单例模式:每次外部请求单例对象时,先检查是否已实例化,如果尚未实例化才进行实例化。理论上只有第一次才会彻底执行同步区块内的代码,既实现了延迟加载,又是线程安全的单例模式
4、静态内部类单例
1 2 3 4 5 6 7 8 9 | class InternalSingleton{ private static class SingletonHolder{ private final static InternalSingleton INSTANCE=new InternalSingleton(); } private InternalSingleton(){} public static InternalSingleton getInstance(){ return SingletonHolder.INSTANCE; } } |
饿汉式单例虽然线程安全,但类装载时创建对象会浪费内存而静态内部类单例模式正好克服了这一点。因为其采用类级内部类(只有在第一次被使用的时候才会被装载),类装载的时候不初始化对象。使用JVM静态初始化器进行初始化变量时,JVM会隐含为我们执行synchronized进行加互斥锁的同步控制,从而同时实现延迟加载和线程安全
5、枚举实现单例
1 2 3 4 5 | enum EnumSingleton{ INSTANCE; public void doSomeThing(){ } } |
优点是线程安全,调用效率高,天然防止反射和反序列化漏洞 。缺点就是不能实现延迟加载