一次代码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以后的版本。
相关推荐
单例模式的并发问题通常出现在延迟初始化(Lazy Initialization)的情况下,即只有在第一次调用`getInstance()`时才创建实例。为了解决这个问题,作者将`createClient()`方法改为同步的(synchronized),确保同一...
Gitlab 代码 review 插件是开发者们在进行代码审核时的一个强大工具,它专为内网环境下的 Gitlab 平台设计。该插件旨在优化源码浏览体验,提高团队协作效率,确保代码质量。在本文中,我们将深入探讨 Gitlab 代码 ...
本文将根据“Coding Review Checklist(代码审查清单)”的内容,详细解析其涉及的关键知识点。 #### 二、常规项 1. **代码运行性**:确认代码能够正常运行,这是最基本的要求。如果代码无法运行,那么后续的所有...
1. **定期进行Code Review**:确保每周至少有一次40分钟的Code Review会议,这有助于保持团队对代码质量的关注度。 2. **合理分组**:小组人数不超过10人,确保至少有一名经验丰富的成员担任组长,他应具备模块设计...
代码审查(Code Review)是软件开发过程中的重要环节,它涉及到多个角色和一系列的步骤,目的是在开发初期就发现代码中的错误,提高代码质量,促进团队成员之间的知识共享和技能提升。在这份代码审查指南中,将详细...
首先,ReviewBoard是一款开源的代码审查工具,它允许开发者提交代码供其他团队成员审核,提供了一个方便的界面来讨论代码变更。Tao-ReviewBoard是Eclipse的一个插件,用于与ReviewBoard集成,使得在Eclipse中可以...
ReviewBoard是一款强大的代码审查工具,它提供了一个web界面,让开发者提交代码变更请求,同事或领导可以查看并提供反馈。在`reviewBoard安装过程.docx`中,你将学习如何下载ReviewBoard,配置数据库连接,安装必要...
我一直认为CodeReview(代码审查)是软件开发中的最佳实践之一,可以有效提高整体代码质量,及时发现代码中可能存在的问题。包括像Google、微软这些公司,CodeReview都是基本要求,代 我一直认为CodeReview(代码...
了解代码review做的ppt,可以帮助人理解代码review的概念
**代码审查(Code Review)是软件开发过程中的一个重要环节,旨在提高代码质量,发现潜在的错误,提升团队协作效率,并确保代码遵循最佳实践和项目规范。本文将深入探讨代码审查的原理、步骤以及如何有效地执行代码...
静态测试方法之代码审查(CodeReview)的清单。代码审查可以帮助提高代码质量,避免由于代码习惯而造成的bug。下面列出的这些要点因该可以作为大部分代码审查的指导,如果是Java应用的话,这些建议应该被视作最佳实践...
Git是一种先进的分布式版本控制系统,由林纳斯·托瓦兹开发,旨在取代较为传统的版本控制系统,如SVN和Mercurial...同时,利用GitLab-CI进行持续集成,可以确保每一次代码变更后快速得到反馈,以保持代码库的健康状态。
是reviewboard为实现自动化提交代码的脚本
标题提到的"IDEA代码检视插件Code Review Helper"是针对IntelliJ IDEA集成开发环境的一款强大工具,旨在提升代码审查的效率和质量。代码审查是软件开发中的一个关键环节,通过它,团队成员可以互相检查彼此的代码,...
Jupiter是一款专用于代码审查的工具,旨在帮助软件开发团队提高代码质量和确保代码规范性。代码审查是软件开发过程中的重要环节,它可以帮助发现潜在的错误、提升代码可读性,并促进团队成员之间的交流与学习。...
提供一个很好的代码Review工具。可以设置4个级别,可以对优秀代码进行学习,还可以对有问题的代码进行复查。
在Java项目开发中,代码审查(Code Review)是确保代码质量、遵循最佳实践以及提高团队协作效率的关键步骤。本文档将深入探讨在Code Review过程中常见的问题,并提供实例分析,以帮助开发者避免这些问题。 **第一章...
**Source Insight CodeReview宏**是专门针对Source Insight这款强大的源代码查看和编辑工具设计的一套扩展功能,主要用于代码评审和统计。Source Insight以其强大的代码导航、语法高亮和实时分析能力,深受程序员...
开发编写代码需要知道的基本准则,仅供参考,非原创,如有雷同侵权请联系作者删除 纯属分享