设计模式一:单例模式

1、单例模式的实现方式


java 复制代码
/**
 * 1、饿汉模式
 */
public class Singleton1 {
    private static AtomicInteger count = new AtomicInteger(0);
    private static final Singleton1 instance = new Singleton1();

    public static Singleton1 getInstance(){
        return instance;
    }
}
java 复制代码
/**
 * 2、懒汉模式
 */
public class Singleton2 {
    private static AtomicInteger count = new AtomicInteger(0);
    private static Singleton2 instance = null;
    
    private Singleton2(){}
    public static Singleton2 getInstance(){
        if(instance == null){
            count.incrementAndGet();
            instance = new Singleton2();
        }
        return instance;
    }
    public static int getCount(){
        return count.get();
    }
}
java 复制代码
/**
 * 3、不安全的锁
 */
public class Singleton3 {
    private static AtomicInteger count = new AtomicInteger(0);
    private static Singleton3 instance = null;

    public static Singleton3 getInstance(){
        if(instance == null){
            synchronized (Singleton3.class){
                count.incrementAndGet();
                instance = new Singleton3();
            }
        }
        return instance;
    }
    private Singleton3(){}
    public static int getCount(){
        return count.get();
    }
}
java 复制代码
/**
 * 4、不安全的锁 volatile
 */
public class Singleton4 {
    private static AtomicInteger count = new AtomicInteger(0);
    private static volatile Singleton4 instance = null;

    public static Singleton4 getInstance(){
        if(instance == null){
            count.incrementAndGet();
            instance = new Singleton4();
        }
        return instance;
    }
    private Singleton4(){}
    public static int getCount(){
        return count.get();
    }
}
java 复制代码
/**
 * 5、双重校验锁
 */
public class Singleton5 {
    private static AtomicInteger count = new AtomicInteger(0);
    private static Singleton5 instance = null;

    public static Singleton5 getInstance(){
        if(instance == null){
            synchronized (Singleton5.class){
                if(instance == null){
                    count.incrementAndGet();
                    instance = new Singleton5();
                }
            }
        }
        return instance;
    }
    private Singleton5(){}
    public static int getCount(){
        return count.get();
    }
}
java 复制代码
/**
 * 6、spring静态工厂生成单例对象,单例注册表
 */
public class Singleton6{
    private static AtomicInteger count = new AtomicInteger(0);
    private static HashMap<String, Object> registry = new HashMap<>();

    static {
        Singleton6 instance = new Singleton6();
        registry.put(instance.getClass().getName(), instance);
    }


    public static Singleton6 getInstance(String name){
        if(name == null){
            name = "com.xf.singleton.Singleton6";
        }
        if(registry.get(name) == null){
            try {
                count.incrementAndGet();
                registry.put(name, Class.forName(name).newInstance());
            } catch (InstantiationException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            }
        }
        return (Singleton6) registry.get(name);
    }

    public static int getCount(){
        return count.get();
    }
}

2、spring中的单例实现方式

java 复制代码
/**
*  使用了单例注册列表
*/
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 Invalid timestamp = getMergedBeanDefinition(beanName, false);
         // ...
         //根据Bean定义判断,此判断依据通常来自于组件配置文件的单例属性开关
         //<bean id="date" class="java.util.Date" scope="singleton"/>
         //如果是单例,做如下处理
         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实例
         //<bean id="date" class="java.util.Date" scope="prototype"/>
         else {
            bean = createBean(beanName, mergedBeanDefinition, args);
         }
      }
      // ...
      return bean;
   }
}

spring中的单例不是线程安全的,当涉及到共享数据时需要记性多线程安全性的处理

相关推荐
正在走向自律几秒前
从只写接口到独立交付前后端,飞算JavaAI能给Java后端工程师多少溢价?
java·springboot·ai编程·全栈开发·java求职·飞算javaai·金九银十
a努力。32 分钟前
LangChain Agent消息链路全解析
java·前端·javascript
SL_staff39 分钟前
物模型是设备的数字身份证:属性、事件、服务如何决定IoT系统扩展性
java·物联网·全栈
资深技术分享员1 小时前
Geejing WebBuilder 日志、在线用户、系统监控,出问题时的三个第一现场
java·运维·数据库
卓怡学长1 小时前
w202springboot基于B_S架构的图书信息管理系统
java·spring boot·spring·intellij-idea
走到天涯海角1 小时前
用springBoot写几个简单的接口
java·spring boot·intellij-idea
troy1281 小时前
Java 技术栈全景指南:从基础到微服务的完整知识体系
java·开发语言·微服务
Escalating_xu1 小时前
【C 语言】深入理解指针(2):数组名、数组传参、二级指针与指针数组
java·c语言·开发语言
景熙55231 小时前
JDBC 详解:从原理到实战(含完整可运行 Demo)
java·spring·tomcat·mybatis·jdbc
程序猿乐锅2 小时前
一文讲透缓存穿透、击穿和雪崩
java·redis·spring·缓存·mybatis