设计模式-单例模式
定义
确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
单例模式的优点:
- 在内存中只有一个对象,节省内存空间。
- 避免频繁的创建销毁对象,可以提高性能。
- 避免对共享资源的多重占用。
- 可以全局访问。
饿汉式单例(线程安全,调用效率高,但是不能延时加载)
public class Singleton {
private static ImageLoader instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
懒汉式单例(线程安全,调用效率不高,但是能延时加载)
public class Singleton {
//类初始化时,不初始化这个对象(延时加载,真正用的时候再创建)
private static Singleton instance;
//构造器私有化
private Singleton(){}
//方法同步,调用效率低
public static synchronized Singleton getInstance(){
if(instance==null){
instance=new SingletonDemo2();
}
return instance;
}
}
双重检查锁实现饿汉式单例
public class Singleton {
private volatile static Singleton singleton;
private Singleton() {
}
public static Singleton newInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
静态内部类+饿汉式单例(线程安全,调用效率高,可以延时加载)
public class Singleton {
private static class SingletonClassInstance{
private static final Singleton instance=new Singleton();
}
private Singleton(){}
public static Singleton getInstance(){
return SingletonClassInstance.instance;
}
}
枚举类
单例注册表(spring的单例实现原理)
看下spring的源码:
public abstract class AbstractBeanFactory implements ConfigurableBeanFactory{
/** * 充当了Bean实例的缓存,实现方式和单例注册表相同 */
private final Map singletonCache=new HashMap();
public Object getBean(String name)throws BeansException{
return getBean(name,null,null);
}
…
public Object getBean(String name,Class requiredType,Object[] args)throws BeansException{
//对传入的Bean name稍做处理,防止传入的Bean name名有非法字符(或则做转码)
String beanName=transformedBeanName(name);
Object bean=null;
//手工检测单例注册表
Object sharedInstance=null;
//使用了代码锁定同步块,原理和同步方法相似,但是这种写法效率更高
synchronized(this.singletonCache){
sharedInstance=this.singletonCache.get(beanName);
}
if(sharedInstance!=null){
…
//返回合适的缓存Bean实例
bean=getObjectForSharedInstance(name,sharedInstance);
}else{
…
//取得Bean的定义
RootBeanDefinition mergedBeanDefinition=getMergedBeanDefinition(beanName,false);
…
//根据Bean定义判断,此判断依据通常来自于组件配置文件的单例属性开关
//
//如果是单例,做如下处理
if(mergedBeanDefinition.isSingleton()){
synchronized(this.singletonCache){
//再次检测单例注册表
sharedInstance=this.singletonCache.get(beanName);
if(sharedInstance==null){
…
try {
//真正创建Bean实例
sharedInstance=createBean(beanName,mergedBeanDefinition,args);
//向单例注册表注册Bean实例
addSingleton(beanName,sharedInstance);
}catch (Exception ex) {
…
}finally{
…
}
}
}
bean=getObjectForSharedInstance(name,sharedInstance);
}
//如果是非单例,即prototpye,每次都要新创建一个Bean实例
//
else{
bean=createBean(beanName,mergedBeanDefinition,args);
}
}
…
return bean;
}
}