一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情。
单例模式类只有一个实例。类通过构造器私有化不允许在外部实例化类对象。
饿汉模式
不管是否使用,一上来就初始化对象。由于是在加载时创建,是线程安全的。
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){
}
public static Singleton getInstance() {
return instance;
}
}
懒汉模式
在需要使用时才创建对象。由于可能存在线程争抢,是线程不安全的。
public class Singleton {
private static Singleton instance;
private Singleton (){
}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
懒汉加锁
在创建对象的时候加synchronized
保证线程安全
缺点:在对象创建以后是不需要synchronized的,导致效率降低。
public class Singleton {
private static Singleton instance;
private Singleton (){
}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
双重判断
使用volatile
保证内存可见性,只在创建对象的时候加锁synchronized
public class Singleton {
private volatile static Singleton instance;
private Singleton (){
}
public static Singleton getInstance() {
if (instance== null) {
synchronized (Singleton.class) {
if (instance== null) {
instance= new Singleton();
}
}
}
return singleton;
}
}
静态内部类
原理:只在获取对象的时候才会加载内部类,类加载是线程安全的。
第一次加载Singleton类时并不会初始化sInstance,只有第一次调用getInstance方法时虚拟机加载SingletonHolder 并初始化sInstance ,这样不仅能确保线程安全也能保证Singleton类的唯一性。
public class Singleton {
private Singleton(){
}
public static Singleton getInstance(){
return SingletonHolder.sInstance;
}
private static class SingletonHolder {
private static final Singleton sInstance = new Singleton();
}
}
spring中的单例
spring容器中的bean默认已单例方式存在。spring容器中的对象在BeanFactory创建以后存在缓存中,获取对象实例的时候直接从缓存中获取,并注入到其他对象中。
// 部分逻辑代码
public abstract class AbstractBeanFactory implements ConfigurableBeanFactory{
/**
* 单例对象缓存map
*/
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{
//synchronized 保证线程安全
synchronized(this.singletonCache){
sharedInstance=this.singletonCache.get(beanName);
}
if(sharedInstance!=null){
//返回缓存Bean实例
bean=getObjectForSharedInstance(name,sharedInstance);
}else{
RootBeanDefinition mergedBeanDefinition=getMergedBeanDefinition(beanName,false);
if(mergedBeanDefinition.isSingleton()){
synchronized(this.singletonCache){
sharedInstance=this.singletonCache.get(beanName);
if(sharedInstance==null){
try {
//创建Bean实例
sharedInstance=createBean(beanName,mergedBeanDefinition,args);
//添加到缓存
addSingleton(beanName,sharedInstance);
}catch (Exception ex) {
}finally{
}
}
}
bean=getObjectForSharedInstance(name,sharedInstance);
}
}
return bean;
}
}
单例模式是最简单、最常用的设计模式。