单例模式以及延迟加载
发表于2014/10/21 23:56:04 830人阅读
分类: 随写
延迟加载,也叫延迟实例化,延迟初始化等,主要表达的思想就是:把对象的创建延迟到使用的时候创建,而不是对象实例化的时候创建。这种方式避免了性能的浪费。
当创建一个对象的子对象开销比较大时,而且有可能在程序中用不到这个子对象,那么就可以考虑用延迟加载的方式来创建子对象。另外就是当一个程序启动时,需要创建多个对象,但仅有几个对象需要立即使用,那么可以将一些不必要的初始化工作延迟到使用的时候。这样可以提高程序的启动速度。
实例一:
public Class Singleton
{
private static Singleton instance;
private Singleton(){ } //私有无参构造
public static Singleton getInstance(){
If(instance==null){
Instance=new Singleton();
}
Return instance;
}
}
构造函数私有,方法静态。
问题:无法保证线程安全,当有多个线程同时访问getInstance的时候,此时若对象为空,就会出现会多个线程同时产生多个Singleton对象。
此时我们可以修改一下上面的代码,如实例二
实例二:
public class Singleton
{
private static Singleton instance;
private static object _lock=new object();
private Singleton()
{
}
public static Singleton GetInstance()
{
if(instance==null)
{
lock(_lock)
{
if(instance==null)
{
instance=new Singleton();
}
}
}
return instance;
}
}
上述代码使用了双重锁方式较好地解决了多线程下的单例模式实现。先看内层的if语句块,使用这个语句块时,先进行加锁操作,保证只有一个线程可以访问该语句块,进而保证只创建了一个实例。再看外层的if语句块,这使得每个线程欲获取实例时不必每次都得加锁,因为只有实例为空时(即需要创建一个实例),才需加锁创建,若果已存在一个实例,就直接返回该实例,节省了性能开销。
实例三:
public class Singleton
{
private static Singleton instance = new Singleton();
private Singleton() { }
public static Singleton getInstance()
{
return instance;
}
}
这个方法保证了在第一次加载的时候实例被初始化,且保证了线程安全。但是为进一步要求,我们想要在使用的时候才才初始化Singleton对象,及延迟加载。那么可以使用实例四方法。
实例四:
public class Singleton {
private Singleton() { }
private static class SingletonHolder {
static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
public static void main(String [] args)
{
Singleton.getInstance();
}
}
该方法中Singleton 有一个静态内部类SingletonHolder,内部类在外部加载的时候并不会加载,在有在调用getInstance才回加载。另外SingletonHolder类使用Private修饰以确保外部类不能访问。