所谓“懒汉式”与“饿汉式”的区别,是在与建立单例对象的时间的不同。
“懒汉式”是在你真正用到的时候才去建这个单例对象
“饿汉式”是在不管你用的用不上,一开始就建立这个单例对象
单例模式属于创建型模式,提供了一种创建对象的最佳方式
在系统的内存中,该类的实例对象有且仅有一个,称之为单例模式。java 中 RunTime 就是单例模式。
注意:
1.单例类只能有一个实例
2.单例类必须自己创建自己的唯一实例
3.单例类必须给所有其他对象提供这一实例
饿汉式
public class SingletonEH { /** * 是否Lazy初始化:否 * 是否多线程安全:否 * 描述:这种方式比较常用,但容易产生垃圾对象 * 优点:没有加锁,执行效率会提高 * 缺点:类加载时就初始化,浪费内存 * 它基于classloader机制避免了多线程的同步问题 * instance在类装载时就实例化,虽然导致类装载的原因有很多种, * 在单例模式中大多数都是调用 getInstance 方法, * 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载, * 这时候初始化 instance 显然没有达到 lazy loading 的效果。 */ private static SingletonEH instance=new SingletonEH(); private SingletonEH(){} public static SingletonEH getInstance(){ System.out.println("instance:"+instance); System.out.println("加载饿汉式"); return instance; } }
饿汉就是类一旦加载,就把单例初始化完成,保证getInstance的时候,单例是已经存在的了。
懒汉式
public class SingletonLH { /** *是否 Lazy 初始化:是 *是否多线程安全:否 *实现难度:易 *描述:这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。 *这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作。 */ private static SingletonLH instance; private SingletonLH (){} public static SingletonLH getInstance() { if (instance == null) { instance = new SingletonLH(); } return instance; } }
而懒汉比较懒,只有当调用getInstance的时候,才回去初始化这个单例。
1、线程安全:
饿汉式天生就是线程安全的,可以直接用于多线程而不会出现问题。
懒汉式本身是非线程安全的,为了实现线程安全有几种写法。
public class SingletonLHsyn { /** *是否 Lazy 初始化:是 *是否多线程安全:是 *实现难度:易 *描述:这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。 *优点:第一次调用才初始化,避免内存浪费。 *缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。 *getInstance() 的性能对应用程序不是很关键(该方法使用不太频繁)。 */ private static SingletonLHsyn instance; private SingletonLHsyn (){} public static synchronized SingletonLHsyn getInstance() { if (instance == null) { instance = new SingletonLHsyn(); } return instance; } }
2、资源加载和性能:
饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用单例,都会占用内存,但是相应的,在第一次调用时速度也会更快,因为其资源已经初始化完成。
懒汉式,会延迟加载,在第一次使用该单例的时候才会实例化对象出来,第一次调用时要初始化。所以会有些延迟
双重锁安全验证:这种方式采用双锁机制,安全且在多线程情况下能保持高性能.。( 推荐)
public class Singleton{
private Singleton();
private static Singleton instance;
public static Singleton getInstance(){
if(instance==null){
synchronized(Singleton.class){
instance=new Singleton();
}
}
return instance;
}
}