这里介绍五种单例模式的实现。
饿汉模式
单例模式主要有五种,先列出饿汉模式,饿汉,顾名思义,就想快点new出对象。想来,只要把静态变量指向需要new的对象,就能在构造方法执行之前生成:
|
|
这种模式的特点是,线程安全,资源浪费和加载慢(可能情形)。
内部类懒加载模式
饿汉模式不是懒加载,取其优点,可以构造一种内部类懒加载模式,比如把一开始的静态字段放在私有静态内部类中,这样可以保证线程安全:
|
|
懒汉模式
延迟加载还有另一种形式,被称作懒汉模式。在这种模式中,字段也不和new创建对象的代码捆绑了,为了保证线程安全,将newInstance()用synchronized修饰:
|
|
这种方法的缺点是,每次只有一个线程可以执行newInstance(),而实际上很多时候,可以先判断一下实例是否已经存在,已经存在就没必要调用synchronized修饰的方法了,这样可以大大提高程序的运行成本。
双重检查加锁的懒汉模式
承接前面的分析,可以考虑将sychronized放入newInstance()内部,在它之前先判断一下对象是否已经存在:
|
|
newInstance方法中的代码很容易理解,这里要注意的是,singleton = new Singleton04()这一行代码在具体执行中在底层可能出现指令重排的情况,引用赋值和初始化对象在单线程内重排后并不影响结果,但多线程下,新的线程拿到的singleton引用指向的对象可能并没有完成初始化,所以需要添加volatile关键字。
枚举模式
|
|
《Effective Java》中在前面章节提到过枚举模式是实现单例的最佳方法,后面章节再次提到过枚举模式,因为它不仅仅简单高效且线程安全,而且在在反序列化的时候,也能保证对象只有一个,不需要额外的处理。