常用单例模式解析
单例模式是一种比较常用且简单的设计模式,单例模式限制了待创建的对象在内存中有且仅有一个。
一.非线程安全的单例模式
public classSingleton{
public static Singletion instance;
private Singleton(){
}
public Singletion getInstance(){
if(instance==null){ //(1)
instance =newSingleton();(2)
}
return instance;
}
}
1.单例模式代码特点概述:该单例模式instance必须是static的,getInstance是静态的方法,构造函数必须设置为私有函数
2.多线程环境分析:假设存在两个线程:线程1和线程2,假如线程1和线程2同时访问Singleton.getInstance()方法,此时假设线程1先执行步骤(1),进入if内部,进行对象的创建工作(对象的创建通常分为两部,第一步在java堆中分配对象所需要的内存,第二步将内存地址分配给instance),与此同时线程2也执行步骤(1),但是线程1尚未执行到创建对象的第二步,此时instance==null,所以线程2同样进入了if语句的内部,再次创建了一个Singleton对象。
该单例模式姑且称其为模式1,该模式在单线程的环境下可以实现单例,但是在多线程的环境下无法实现单例。
二.适用于多线程环境下的单例模式
public classSingleton{
public static Singleton instance;
private Singleton(){
}
public static Singleton getInstance(){
synchronized(Singleton.class){//(0)
if(instance==null){//(1)
instance=newSingleton();//(2)
}
}
return intance;//(3)
}
}
1.多线程环境性能分析:该单例模式适用于多线程环境,若存在两个线程同时访问Singleton.getInstance()方法,假定线程1先执行步骤(0),步骤(1),进入if语句内部,synchronize关键字会加一把同步锁,接着线程1顺次执行(1),(2),(3)步骤创建一个对象,同样假设线程1在执行步骤(0),(1),(2)时,线程2进入方法内部,执行到步骤(0),发现同步锁未被释放,线程2此时只能等待,等待线程1执行完(1),(2),(3)释放同步锁后,线程2方能执行步骤(1),最后直接跳转到(3)。完成多线环境下的单例模式的设计。
2.该单例模式可以适应多线程的环境,但是性能表现不好,因为线程每次访问getInstance()时,都会添加一把同步锁,而添加同步锁是非常消耗性能的事情,所应该单例模式的性能表现不佳
三.双重判断的单例模式
public classSingleton{
public static Singleton instance;
private Singleton(){
}
public static Singleton getInstance(){
if(intance==null){(0)
synchronized(Singleton.class){//(1)
if(instance==null){//(2)
instance=newSingleton();//(3)
}
}
}
return instance;//(4)
}
}
1.多线程环境下的性能分析:该单例子模式相比较于方式二,主要减少了同步锁的添加,从这方面对效率进行优化
2.利用了双重if循环实现了单例模式,实现的代码比较复杂,容易出错。
四.改进的单例模式
public classSingleton{
public static Singleton instance = newSingleton();
private Singleton(){
}
public static Singleton getInstance(){
return instance;
}
}
1.该单例模式可以适应线程环境的要求,利用Singleton类只被加载一次的特性,完成instance的创建
2.该单例模式拥有一个缺陷,无论是否使用该对象,一旦Singleton类被加载那么instance就分配了内存,在加载速度和内存的利用情况方面有缺陷
五.静态内部类实现的单例模式
public classSingleton{
public static class SingletionHolder{
public static final Singleton instance =new Singleton();}
private Singleton(){}
public static Singleton getInstance(){
return Singleton.instance;//(4)
}
}
1.该单例模式利用类加载机制来适用于多线程的环境,并且利用了静态内部类只在使用时才加载的特性克服了方法4的缺点,只有在使用到该对象是才会分配内存空间,对内存的利用非常合理。