冷风阵阵,众人安置妥当,小何不见林风身影,只得四处寻找,恰好见到从里面走出的齐泰,“齐大人,是否见过林大人?”

Java设计模式探讨之单例模式


单例模式是在平时的项目开发中比较常见的一种设计模式,使用比较普遍,网上的资料也是一抓一大把,小Alan也来凑凑热闹,为以后充实点设计模式相关的内容做个简单的开篇。

单例模式是一种创建对象的模式,用于产生这个类的一个具体的实例对象,跟普通的对象创建比起来就那么一点点区别,区别就在于它可以确保项目中的一个类只会产生一个具体的对象实例。而不会出现第二个对象实例,第三个对象实例。所有使用到这个对象实例的地方实际上用的都是同一个对象,这就是所谓的单例模式,对于初学者还可能陌生,对于老司机们来讲这可是最最简单的设计模式之一。

 

在Java中使用单例模式有哪些好处嘞?

①对于频繁使用、经常使用的对象,可以省略创建对象也就是没对象的需要new一个对象所花费的时间,这对于那些重量级的对象来说,还是能少来一个就少来一个,用老对象就好了,减少开销;

②创建对象的次数变少了,对系统内存使用的频率就会降低,这样就减轻了GC的压力,缩短了GC所耗费的时间;

③开发项目的过程中遇到类只需要一个对象实例的时候,那么就是选择这模式无疑了。

 

单例的实现1:

下面给出一个单例的实现,这个实现是so easy的,代码如下:

 1 /**
 2  * 单例模式
 3  * @author AlanLee
 4  *
 5  */
 6 public class Singleton
 7 {
 8     
 9     // 饿汉模式
10     private static Singleton instance = new Singleton();
11     
12     private Singleton()
13     {
14         System.out.println("Singleton is create");
15     }
16     
17     public static Singleton getInstance()
18     {
19         return instance;
20     }
21     
22 }

使用这种方式创建单例对象有几点需要特别注意。

第一点:我们要保证我们的项目中不会有人意外的创建多余的对象实例的话,我们需要把Singleton的构造函数设置为private私有的。这样其他开发人员就不能随便的创建这个类的对象实例了,从而避免该类的对象实例被错误的创建出来;

第二点:instance对象必须是private私有的并且static静态化的。如果不是private私有的,那么instance的安全性无法得到保证。一不小心可能就被其他开发人员来个Singleton.instance=xxx的,那这个对象也就被改变了,如果=null的话,可想而知,在使用这个对象实例的使用,迎接你的将是空对象异常的怀抱。其次,因为工厂方法getInstance()是static静态方法,因此方法中返回的变量也得是static的。

 

探讨:每种实现方式在高并发环境下性能如何呢,每种实现方式有木有什么不足之处?

这个单例模式的实现方式性能是非常好的,因为工厂方法getInstance()只是简单的返回instance对象实例,并没有任何锁操作,因此在并行程序中,还是会有比较不错的表现滴。

但是这种方式有一点不足,就是instance对象实例在什么时候被创建出来是不受控制的,基础好点的都知道static成员会在类第一次初始化的时候被创建,这个时候可不一定是工厂方法getInstance()第一次被调用的时候。

假设你的单例模式是这样的,代码如下:

 1 /**
 2  * 单例模式:实例对象第一次初始化的问题
 3  * 
 4  * @author AlanLee
 5  *
 6  */
 7 public class Singleton2
 8 {
 9     public static int STATUS = 1;
10 
11     private static Singleton2 instance = new Singleton2();
12 
13     private Singleton2()
14     {
15         System.out.println("Singleton2 is create");
16     }
17 
18     public static Singleton2 getInstance()
19     {
20         return instance;
21     }
22 
23 }

注意,这个单例还包含另一个静态成员STATUS。此时,在任何地方引用这个STATUS都会导致instance对象实例被创建(任何对Singleton2方法或者字段的引用,都会导致类初始化,并创建instance实例,但是类初始化只有一次,因此instance实例永远只会被创建一次)。

比如:System.out.println(Singleton.STATUS);

上述println会打印出:

可以看到,就算我们没有要求创建instance单例对象,new Singleton2()也会被调用。

如果不在乎这个小小的不足之处,这种单例模式的实现方式是一种不错的选择。它容易实现,代码易读而且性能优越。

 

单例的实现2:

如果你想精准的控制instance的创建时间,那么就需要使用下面这种方式,一种支持延迟加载的策略,它只会在instance被第一次使用时才会创建对象。代码如下:

 1 /**
 2  * 单例模式之懒汉模式
 3  * 
 4  * @author AlanLee
 5  *
 6  */
 7 public class LazySingleton
 8 {
 9     private static LazySingleton instance = null;
10 
11     private LazySingleton()
12     {
13         System.out.println("LazySingleton is create");
14     }
15 
16     public static synchronized LazySingleton getInstance()
17     {
18         if (instance == null)
19         {
20             instance = new LazySingleton();
21         }
22         return instance;
23     }
24 }

最初我们并不需要实例化instance对象实例,只有工厂方法getInstance()被第一次调用时才会创建单例对象。但是在高并发环境下,为了防止对象被对此创建,我们不得不使用synchronized进行方法同步。这种实现的好处是,充分利用了延迟加载,只有在真正需要时才创建对象。但坏处也很明显,并发环境下加锁,在锁竞争激烈的时候会对性能产生一定的影响。

此外,还有一种被称为双重检查模式的方法可以用于创建单例。这是一种非常丑陋、复杂的方法,甚至在低版本的JDK中都不能保证正确性。不推荐使用,也没必要在这种方法上花费太多时间。

 

单例的实现3:

在上述的单例模式实现方式中,可说是各有千秋,那么第三种方式便是结合两者的优势的一种两全其美的实现方式,代码如下:

 1 /**
 2  * 无懈可击之单例模式
 3  * 
 4  * @author Alanlee
 5  *
 6  */
 7 public class StaticSingleton
 8 {
 9     
10     private StaticSingleton()
11     {
12         System.out.println("StaticSingleton is create");
13     }
14 
15     private static class SingletonHolder
16     {
17         private static StaticSingleton instance = new StaticSingleton();
18     }
19 
20     public static StaticSingleton getInstance()
21     {
22         return SingletonHolder.instance;
23     }
24     
25 }

上述代码实现了一个单例模式,并且同时拥有前两种方式的优点。首先工厂方法getInstance()没有使用同步锁,这使得在高并发环境下性能得到了提升。其次,只有在工厂方法getInstance()被第一次调用时,StaticSingleton的实例才会被创建。这种方式巧妙地使用了内部类和类的初始化方式。内部类SingletonHolder被申明为private私有的,这使得我们不可能在外部访问并初始化它。而我们只能在工厂方法getInstance()内部对SingletonHolder类进行初始化,利用虚拟机的类初始化机制创建单例对象。

 

结束语:宠辱不惊,闲看庭前花开花落;去留无意,漫随天外云卷云舒......小Alan除了喜欢看技术书籍,还是一个武侠玄幻小说爱好者呢!希望自己在IT的这条道路上就能像小说中的主人公一样,纵然困难重重,亦能化险为夷成就康庄大道,至于坐拥美女环抱啥的,小Alan可不敢想啊,还是有一个深爱自己的女人足以。

 

可爱博主:AlanLee

博客地址:http://www.cnblogs.com/AlanLee

本文出自博客园,欢迎大家加入博客园。

 

当前文章:http://hnhdqp.com/ieq9c6q7no/index.html

发布时间:2019-02-20 02:54:25

推牌9扑克牌大小规则 捕鱼加微信客服送分 最新全民棋牌现金版 血战到底麻将技巧八 单机四人麻将破解版 斗地主赢话费可以提现 能提现捕鱼游戏 彩金宏辉单机版下载 棋牌游戏作弊弄钱教程 网络用语丧是什么意思

编辑:纯密辛开

相关新闻

高档餐饮转型,公款吃喝少了几分?

2019-02-20 01:07:56

厦门酵勤缆投资有限公司

太极完美越狱教程 TaiG for Mac

2019-02-20 09:41:50

铜仁乐耸诩商贸有限公司

马伊琍携俩女儿出行 罕见秀二人画画合照

2019-02-20 02:46:45

永新眉劝有限公司

《圣斗士星矢》将引进内地 现业内新片推介会片单

2019-02-20 04:27:45

寿光沦严美容美发化妆学校

热门推荐

  • 复旦大学开创第三类存储技术:写入速度为U盘一万倍
  • 日本研发出超薄皮肤:可监测脉搏速度,还能显示动态表情
  • 专属特权!《新天龙八部》人气新服明日强势开启
  • 西藏晒五年反腐成绩单:共查办职务犯罪案件355件392人
  • 工行e卡送福利:6GB全国流量免费拿
  • 美国纽约曼哈顿爆炸案嫌犯被控支持恐怖组织等罪名
  • 中央机关及其直属机构2018年度考试录用公务员工作启动
  • 广东石油化工学院2017级新生军训圆满结束
  • 银监会:暂停网贷机构开展校园贷
  • 四川茂县曾发生惨重地震灾难 叠溪古城消逝(图)
  • 河北新闻网版权所有 本站点信息未经允许不得复制或镜像 法律顾问:苹果安装熊猫四川麻将 南通长牌官网下载
  • 扑克皇者 copyright ? 2000 - 2016
  • 新闻热线:0311-67563366 广告热线:0311-67562966 新闻投诉:0311-67562994
  • 冀ICP备 09047539号-1 | 互联网新闻信息服务许可证编号:1312006002
  • 广播电视节目制作经营许可证(冀)字第101号|信息网络传播视听节目许可证0311618号
  • 左右棋牌人工客服电话 左右棋牌客服电话