1、为何须要单例模式?
能够保证一个类仅有一个实例,控制实例数目,节约系统的资源。好比:数据库的链接池。一些资源管理器常被设计成单例模式html
2、怎么使用java
2.1 饿汉式
是否多线程安全:是
是否 Lazy 初始化:否
描述:
优势:没有加锁,执行效率提升
缺点:在某些状况下,不是由于调用getInstance而致使的类初始化的话,那么会存在浪费内存的状况
该模式是基于classLoader机制避免多线程的问题,当读取类的静态字段(类静态常量不是)、调用类的静态方法时(固然还有不少状况会触发类的初始化,更多细节参考深刻理解JVM虚拟机)。会触发类的初始化。当进行初始化时,JVM会为类的静态语句块和为类变量赋值操做,生成<clinit>的汇编指令,该指令保证只有一个线程运行。会阻塞其余线程,所以能保证只初始化一次。
备注:有人说在类加载时就会初始化,浪费内存,我的感受是不对的。首先JVM的类加载会进行类的加载(加载class文件),验证(验证字节码文件),准备(为类变量分配内存并赋初值),解析(将符号引号转为直接引用);紧接着再初始化,可是须要注意的是,已经说明JVM何时才会为类进行初始化。因此,说类在加载时就会初始化,我的感受是不对的。若是我的讲述错误,请留言数据库
代码示例:编程
public class Singleton { private static Singleton instance = new Singleton(); private Singleton (){} public static Singleton getInstance() { return instance; } }
2.二、静态内部类
是否多线程安全:是
是否 Lazy 初始化:是安全
代码示例:多线程
public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return SingletonHolder.INSTANCE; } }
2.三、双检锁/双重检验锁(DCL,double checked locking)
是否多线程安全:是
是否 Lazy 初始化:是
描述:
缺点:实现复杂,且效率太低,每次都须要判断一次if。不推荐使用
请注意
若是singleton变量没有加上volatile,那么就是非线程安全的。来模拟一下:
线程A走到④处,初始化完毕了singleton,线程B走到②处。由于没有加volatile,因此此时singleton可能不会对其余内存当即可见,因此线程B也走到了④,所以,实例化了2个对象。
代码示例:并发
public class Singleton { private volatile static Singleton singleton; private Singleton (){} public static Singleton getSingleton() { if (singleton == null) { ① synchronized (Singleton.class) { ② if (singleton == null) { ③ singleton = new Singleton(); ④ } } } return singleton; } }
2.四、枚举
是否多线程安全:是
是否 Lazy 初始化:是
描述:推荐使用
对于枚举类来讲,每一个对象(INSTANCE)都是被public static final修饰的。其次构造函数默认私有。因此用来实现单例模式,是很是适合的。
在Effective Java第二版的第77条,推荐使用枚举实现单例模式。
代码示例:函数
public enum Test{ INSTANCE; private Singleton singleton; Test() { singleton = new Singleton; } public Singleton getInstance() { return singleton; } }
有关参考:
java并发编程实战
EffectiveJava 第二版
http://www.runoob.com/design-...线程