关闭

设计模式——单例模式

2339人阅读 评论(0) 收藏 举报
分类:

为什么需要单例模式

有时候我们需要使用一个实用类A,这个类A专门提供一些公共功能供别人调用,而本身并不会处理业务逻辑。由于类A会被许多类乃至线程调用,假设我们的程序非常庞大,在运行的过程中,会访问这个类A100次,为了调用类A的方法,需要先创建A的对象,A a = new A()。这种方法在对A的访问量较少的情况下没问题,但是像我们这种情况,就会创建100个类A的实例,这100个实例是要占用内存的,从这种角度来说,就造成了大量不必要的开销。而单例模式,在整个程序生命周期中,只有一个实例,这样就不会造成不必要的内存消耗。

单例模式的设计

为了让整个生命周期内只有一个实例,我们可以这样做:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public class Singleton {  
  2.   
  3.     private static Singleton sSingleton;  
  4.   
  5.     private Singleton() {  
  6.     }  
  7.   
  8.     public static Singleton getInstance() {  
  9.         if (sSingleton == null) {  
  10.             sSingleton = new Singleton();  // line A  
  11.         }  
  12.   
  13.         return sSingleton;  
  14.     }  
  15.   
  16. }  
上述做法好像没啥问题,由于mSingleton是静态的,因此能够保证程序运行过程中只存在一个实例。但是针对多线程情况,就可能有问题,比如有2个线程同时并发调用getInstance方法,并且同时执行到了line A,这个时候还是会各自new一个对象出来,也就是说,存在了两个实例,这违背了单例模式的概念,下面我们改进一下:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public class Singleton {  
  2.   
  3.     private static Singleton sSingleton;  
  4.   
  5.     private Singleton() {  
  6.     }  
  7.   
  8.     public static Singleton getInstance() {  
  9.         synchronized (Singleton.class) {  
  10.   
  11.             if (mSingleton == null) {  
  12.                 sSingleton = new Singleton();  
  13.             }  
  14.             return sSingleton;  
  15.         }  
  16.   
  17.     }  
  18.   
  19. }  
上述做法的确是没啥问题了,getInstance方法中对mSingleton对象加锁,可以保证同一时刻只有一个线程能够进入getInstance方法。现在考虑一种情况,还是我们的比较庞大的工程,在某个变态的时刻,我们需要访问Singleton对象100次,注意是高并发下的同时访问,会是什么情形呢?大概是这样的:100个线程进入getInstance方法以后开始抢mSingleton的所有权,这个时候,有一个线程获得了锁,然后顺利地得到了Singleton实例,接着会是什么情形呢?应该是这样的:剩下99个线程开始抢mSingleton的所有权,一直这样类推下去,可能有一个线程运气比较差,抢了100次才抢到锁,程序的表现可能是这样的:这个运气差的线程被阻塞在getInstance方法中,迟迟无法返回,如果需要返回数据给ui的话,那么ui将迟迟不会得到更新。

我们需要看一下上述代码,真的需要每次进入getInstance方法都要获得锁吗?其实不是的,整个Singleton类中,对mSingleton进行访问的地方分为两类:读和写,而且仅当mSingleton为null的时候才会写,mSingleton一旦创建完毕,后面就只剩下读操作了,再怎么高并发也没什么关系了,反正mSingleton已经是现成的,直接读就可以了,看如下采用double-check机制的改进代码:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public class Singleton {  
  2.   
  3.     private volatile static Singleton sSingleton;  
  4.   
  5.     private Singleton() {  
  6.     }  
  7.   
  8.     public static Singleton getInstance() {  
  9.         if (sSingleton == null) { // line A  
  10.             synchronized (Singleton.class) { // line C  
  11.                 if (sSingleton == null)  
  12.                 sSingleton = new Singleton();  // line B  
  13.             }  
  14.         }  
  15.   
  16.         return sSingleton;  
  17.     }  
  18.   
  19. }  
上述代码近乎完美,可以满足几乎所有场合(采用反射和类加载器另当别论)。上述代码的好处在于:第一次创建实例的时候会同步所有线程,以后有线程再想获取Singleton的实例就不需要进行同步,直接返回实例即可。还有double-check的意义在于:假设现在有2个线程A和B同时进入了getInstance方法,线程A执行到line A行,线程B执行到line B行,由于B线程还没有初始化完毕,sSingleton还是null,于是线程A通过了sSingleton==null的判断,并且往下执行,碰巧,当线程A执行到line C的时候,线程B初始化完毕了,然后线程B返回,注意,如果没有double-check,这个时候线程A就执行到了line B,就会再次初始化sSingleton,这个时候Singleton实际上被new了两次,已经不算完全意义上的单例了,而有了double-check,就会再进行一次为null的判断,由于B线程已经初始化了sSingleton,所以A线程就不会再次初始化sSingleton。

0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

设计模式——单例模式的几种实现方式

1.饿汉式:静态常量 这种方法非常的简单,因为单例的实例被声明成static和final变量了,在第一次加载类到内存中时就会初始化,所以会创建实例本身是线程安全的。public class Singl...
  • bingogirl
  • bingogirl
  • 2016-09-01 00:03
  • 1169

设计模式:单例模式(Singleton)

单例模式在23个设计模式中算得上是最简单的一个了,也行你会有异议,那就换成“最简单之一”,这样就严谨了很多。   单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。   适用性:当类...
  • u013256816
  • u013256816
  • 2016-03-23 21:37
  • 4735

java设计模式之单例模式(几种写法及比较)

概念:   java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例、饿汉式单例、登记式单例。   单例模式有以下特点:   1、单例类只能有一个实例。  ...
  • tolcf
  • tolcf
  • 2015-10-21 22:56
  • 6142

C++设计模式[二]单例模式

接着就是单例模式;个人理解就是把创建方法改为私有,然后再内部实例化,禁止外部创建对象。 何为单例模式,在GOF的《设计模式:可复用面向对象软件的基础》中是这样说的:保证一个类只有一个实例,并提供一个...
  • langb2014
  • langb2014
  • 2015-11-03 16:11
  • 1002

设计模式(二)单例模式的七种写法

面试的时候,问到许多年轻的Android开发他所会的设计模式是什么,基本上都会提到单例模式,但是对单例模式也是一知半解,在Android开发中我们经常会运用单例模式,所以我们还是要更了解单例模式才对。...
  • itachi85
  • itachi85
  • 2016-01-17 10:29
  • 23766

Java四种单例设计模式

Java中的四种单例模式单例模式是最容易理解的设计模式之一,介绍Java中单例模式的四种写法。1.饿汉式单例模式public class Singleton{ private static S...
  • twocold_2010
  • twocold_2010
  • 2016-11-20 15:13
  • 176

单例模式(Singleton)- 最易懂的设计模式解析

前言今天我来全面总结一下Android开发中最常用的设计模式 - 单例模式。 关于设计模式的介绍,可以看下我之前写的:1分钟全面了解“设计模式” 目录1. 引入1.1 解决的是什么问题之前说过,设...
  • carson_ho
  • carson_ho
  • 2016-08-16 17:15
  • 3977

浅谈常见设计模式--单例模式 简单工厂模式

今题那站在这里和大家一起分享最近在一本书上看到的关于设计模式的内容,接下来要讲的设计模式有: 单例模式 简单工厂模式 工厂方法和抽象工厂 代理模式 命令模式 策略模式 门面模式 桥接模式 观察者模式 ...
  • xikai18827083487
  • xikai18827083487
  • 2016-11-13 17:04
  • 895

JAVA设计模式之单例模式

概念:   java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例、饿汉式单例、登记式单例三种。   单例模式有一下特点:   1、单例类只能有一个实例。   2、单例类必须自己自己创建自...
  • jason0539
  • jason0539
  • 2014-04-16 06:51
  • 630330

JavaScript设计模式(一)单例模式、组合模式和外观模式

作者 Joseph Zimmerman http://www.joezimjs.com 创建日期 19 March 2012 本文是介绍 Jav...
  • buptlyz
  • buptlyz
  • 2016-07-25 00:18
  • 409
    个人资料
    • 访问:6209117次
    • 积分:59947
    • 等级:
    • 排名:第55名
    • 原创:332篇
    • 转载:1715篇
    • 译文:19篇
    • 评论:177条
    博客专栏
    网上乐园
    最新评论