一次代码review引发的关于单例模式的思
一次代码调优中发现一个情况,即我在查看memcached的connection时,发现总是维持在100来个左右,当然这看似没什么问题,因为memcached默认connection有1024个。但是我想的是为什么会有100来个,因为我的memcachedclient的产生采用的是单例模式,so let’s get into the code:
我定义了一个memcachedClientFactory类,主要代码如下:
MemcachedClientFactory{ private MemcachedConnectionBuilder memcachedConnectionBuilder; private String servers; private static MemcachedClient memcachedClient; private MemcachedClientFactory(){ } private MemcachedClientFactory(MemcachedConnectionBuilder memcachedConnectionBuilder, String servers){ this. memcachedConnectionBuilder= memcachedConnectionBuilder; this.servers=servers; } public static MemcachedClient createClient(){ if(memcachedClient==null){ this.memcahcedClien= new MemcachedClient(memcachedConnectionBuilder.build(),AddrUtil.get(servers)); } return this.memcahcedClient; } } }
那回到最初的问题,为什么会有100多个连接?上面这个写法真的能保证只产生一个连接?很显然是不能,为什么?多线程并发!问题就出在这里,当有多个线程同时进入createClient()方法时,而且刚好都判断为memcachedClient为null,这时候就产生了多个连接。哈,问题找到了。
改进:
public static synchronizd MemcachedClient createClient(){ if(memcachedClient==null){ this.memcahcedClien= new MemcachedClient(memcachedConnectionBuilder.build(),AddrUtil.get(servers)); } return this.memcahcedClient; }
这样就ok了,改动很简单。程序是没有问题了,而且也能保证只有一个连接。
不过抛开这个问题,我们可以继续就如何解决单例模式下的并发问题深入思考一下。
我总结一下,要解决单例模式在并发下的问题,大概有三种方式:
1. 不使用延迟实例化,而是用提前实例化。
即程序改写为:
Public Class Singleton{ private static Singleton instance=new Singleton(); private Singleton(){}; public static Singleton getInstance(){ return instance; } }
这样做时,jvm在加载类时就立马创建了该实例,所以这样做的前提是,创建该实例的负担不大,我不比过多的考虑性能,并且我们确认该实例是一定会用到的。其实我前面的代码也完全可以使用这个方式:
MemcachedClientFactory{ private MemcachedConnectionBuilder memcachedConnectionBuilder; private String servers; private static MemcachedClient memcachedClien= new MemcachedClient(memcachedConnectionBuilder.build(),AddrUtil.get(servers)); private MemcachedClientFactory(){ } private MemcachedClientFactory(MemcachedConnectionBuilder memcachedConnectionBuilder, String servers){ this. memcachedConnectionBuilder= memcachedConnectionBuilder; this.servers=servers; } public static MemcachedClient createClient(){ return this.memcahcedClient; } } }
不过,看上去似乎没有问题,但是有隐患,即一旦有人不小心调用了memcachedClient.shutdown()方法,那整个程序就无法再生出新的memcachedClient了。当然这是极端情况了,但是为了代码的健壮,可以再改为:
public static MemcachedClient createClient(){ if(memcachedClient==null){ this.memcahcedClien= new MemcachedClient(memcachedConnectionBuilder.build(),AddrUtil.get(servers)); } return this.memcahcedClient; }
2. 就是使用synchronized关键字。
这么做可以保证同步问题,但是我们知道使用synchronized的开销是很大的,会严重影响性能,所以用这个的前提是,你确认不会经常调用这个方法,或者你创建这个instance的开销不会特别大。是否还可以改进,看 下面。
3. 使用“双重检查加锁“,在getInstance中见识使用同步。写法如下
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 instance; } }
这样减少了synchronized出现的次数。当然使用volatile关键字有局限性,就是你的jdk必须是1.5以后的版本。
相关推荐
一次代码调试中发现一个情况,即我在查看memcached的connection时,发现总是维持在100来个左右,当然这看似没什么问题,因为memcached默认connection有1024个。
详细讲述了如何进行代码Review以及代码Review中需要关注的事项
jupiter代码review工具
Gitlab 代码 review 插件,用于浏览内网 Gitlab 源码,通过 chrome 加载即可使用
代码review的好处很多人都知道,但是如何有效的进行代码review呢?看了这个教程,希望对你有所启发。
了解代码review做的ppt,可以帮助人理解代码review的概念
列一份代码审查清单,避免研发犯低级错误
个人总结 C++ 代码审查 reviewboard 详细部署配置说明
是reviewboard为实现自动化提交代码的脚本
代码Review 文档,从网上摘抄下来的,个人感觉很有用,在开发中应该值得提倡
提供一个很好的代码Review工具。可以设置4个级别,可以对优秀代码进行学习,还可以对有问题的代码进行复查。
本文档主要介绍了基于Gitlab搭建代码审查平台以及基于Gitlab-CI搭建持续集成平台。本文档最重要的内容是提供了一套基于Gitlab的代码审查流程的可落地的详细操作方案。
Java项目开发代码Review常见问题实例
我一直认为CodeReview(代码审查)是软件开发中的最佳实践之一,可以有效提高整体代码质量,及时发现代码中可能存在的问题。包括像Google、微软这些公司,CodeReview都是基本要求,代 我一直认为CodeReview(代码...
本文叫你如何进行code review代码检测
开发编写代码需要知道的基本准则,仅供参考,非原创,如有雷同侵权请联系作者删除 纯属分享
代码审核,是对应用程序源代码进行系统性检查的工作。它的目的是为了找到并且修复应 用程序在开发阶段存在的一些漏洞或者程序逻辑错误,避免程序漏洞被非法利用给企业带来不必 要的风险。
如果Tao-ReviewBoard安装好了之后,在代码上右键发现 Pre-Commit to ReviewBoard | Post-Commit to ReviewBoard 这两个选项是灰色不可用,可能是你eclipse的svn插件有问题,我本机使用的是有中文提示的svn插件版本...
1 方便学员学习教师的代码,无需在本机运行IDE即可以代码加亮的方式查看服务器共享的代码。 2 方便开发团队进行Code review。 3 方便教师审查学生代码。 不能做的事(其实本意就是不允许做的): 1 下载文件。 ...
Code Review是一种用来确认方案设计和代码实现的质量保证机制,通过这个机制我们可以对代码、测试过程和注释进行检查。 Code Review主要用来在软件工程过程中改进代码质。代码评审检查文档,统一规范文档、适合规范...