Eureka源码-double check单例模式运用

1.在看源码之前,首先先解释一下什么是double check,以及单例模式中为什么需要double check来进行单例模式的创建?

double check,也叫双重检测,主要利用两次的判断进行校验当前单例的创建情况。

如下面的代码

 static volatile AbstractConfiguration instance = null;

   
 public static AbstractConfiguration getConfigInstance() {
        if (instance == null) {
            Class var0 = ConfigurationManager.class;
            synchronized(ConfigurationManager.class) {
                if (instance == null) {
                    instance = getConfigInstance(Boolean.getBoolean("archaius.dynamicProperty.disableDefaultConfig"));
                }
            }
        }

        return instance;
    }
  • 首先第一层是instance == null , 他主要的作用是减少synchornized锁竞争的压力,避免在大量线程访问的情况下,导致锁升级为重量级锁,从而导致线程之间互斥而进行长时间堵塞,严重的甚至可能导致OOM的情况。所以加第一层可以有效的阻挡部分已经获取单例的线程再次进入,减少线程间锁的竞争压力。
  • 第二层: 主要是保证在获取锁后的线程确保实例是空的情况下在进行创建,保证了单例仅创建了一次。

如上情况,看似已经比较的完美了,但是还有会有问题,问题就出现在多线程调用的时候,由于单例创建的实例存在于公共内存中,当实例创建之后,其他正在创建的实例不一定立马就知道单例的变化,所以还需要一个修饰符Volitile,它不仅仅可以阻止执行过程中指令的重排序,还可以保证线程之间的可见性(通过MESI缓存一致性协议确定),让创建的实例保证有且仅有一个。

2.详细看看这个在Eureka源码中是如何使用的。

还是寻找入口点从EurekaBootstrap启动类入口。

public class EurekaBootStrap implements ServletContextListener {


public void contextInitialized(ServletContextEvent event) {
        try {
            //进行环境初始化
            this.initEurekaEnvironment();
            this.initEurekaServerContext();
            ServletContext sc = event.getServletContext();
            sc.setAttribute(EurekaServerContext.class.getName(), this.serverContext);
        } catch (Throwable var3) {
            logger.error("Cannot bootstrap eureka server :", var3);
            throw new RuntimeException("Cannot bootstrap eureka server :", var3);
        }
    }

}

紧接跟入如下代码:

protected void initEurekaEnvironment() throws Exception {
        logger.info("Setting the eureka configuration..");
        String dataCenter = ConfigurationManager.getConfigInstance().getString("eureka.datacenter");
        if (dataCenter == null) {
            logger.info("Eureka data center value eureka.datacenter is not set, defaulting to default");
            ConfigurationManager.getConfigInstance().setProperty("archaius.deployment.datacenter", "default");
        } else {
            ConfigurationManager.getConfigInstance().setProperty("archaius.deployment.datacenter", dataCenter);
        }

        String environment = ConfigurationManager.getConfigInstance().getString("eureka.environment");
        if (environment == null) {
            ConfigurationManager.getConfigInstance().setProperty("archaius.deployment.environment", "test");
            logger.info("Eureka environment value eureka.environment is not set, defaulting to test");
        }

    }

重点为如下语句:

   String dataCenter = ConfigurationManager.getConfigInstance().getString("eureka.datacenter");

继续跟入:

 public static AbstractConfiguration getConfigInstance() {
        if (instance == null) {
            Class var0 = ConfigurationManager.class;
            synchronized(ConfigurationManager.class) {
                if (instance == null) {
                    instance = getConfigInstance(Boolean.getBoolean("archaius.dynamicProperty.disableDefaultConfig"));
                }
            }
        }

        return instance;
    }

这里就应用了如开始的double check 的代码 。整体的应用流程就是这样,全局创建一个配置实例。

总结

总体的流程图如下所示,需要的朋友可以下载研究保存。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你今天学习了吗?

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值