【第22期】观点:IT 行业加班,到底有没有价值?

Java设计模式---单例模式

转载 2015年07月07日 19:42:10

Java设计模式---单例模式

一、饿汉模式

饿汉模式代码  收藏代码
  1. /**  
  2.  * @ClassName: Singleton_Simple  
  3.  * @Description: 单例模式——饿汉模式   
  4.  * @author Ran  
  5.  * @date 2011-2-4 上午12:46:15  
  6.  *   
  7.  */  
  8. public class Singleton_Simple {  
  9.       
  10.     private static final Singleton_Simple simple = new Singleton_Simple();  
  11.       
  12.     private Singleton_Simple(){}  
  13.       
  14.     public static Singleton_Simple getInstance(){  
  15.         return simple;  
  16.     }  
  17.   
  18. }  

    说明:顾名思义,饿汉模式就是在jvm进程启动并在我们主动使用该类的时候就会在内存中初始化一个单例对象,当我们调用getInstance()的时候直接获取该对象,他的创建是在我们调用getInstance()静态方法之前!

 

二、懒汉模式

懒汉模式代码  收藏代码
  1. /**  
  2.  * @ClassName: Singleton_lazy  
  3.  * @Description: 单例模式——懒汉模式   
  4.  * @author Ran  
  5.  * @date 2011-2-4 上午12:48:41  
  6.  *   
  7.  */  
  8. public class Singleton_lazy {  
  9.   
  10.     private static Singleton_lazy lazy = null;  
  11.       
  12.     private Singleton_lazy(){}  
  13.       
  14.     public static synchronized Singleton_lazy getInstance(){  
  15.         if( lazy == null ){  
  16.             lazy = new Singleton_lazy();  
  17.         }  
  18.         return lazy;  
  19.     }  
  20. }  

    说明:懒汉模式是相对于饿汉模式而言的,在jvm进程启动并在我们主动使用该类的时候不会在内存中初始化一个单例对象,只有当我们调用getInstance()的时候才去创建该对象,他的创建是在我们调用getInstance()静态方法之后,为了并没现象同步问题,我们在getInstance()方法上加了一个锁,这个方法每次只允许一个线程进来,虽然同步问题是解决了,但是相应的性能问题就出现了。

 

三、双锁机制

 

双锁机制 代码  收藏代码
  1. /**  
  2.  * @ClassName: Singleton_DoubleKey  
  3.  * @Description: 单例模式——双锁机制   
  4.  * @author Ran  
  5.  * @date 2011-2-4 上午12:53:50  
  6.  *   
  7.  */  
  8. public class Singleton_DoubleKey {  
  9.   
  10.     private static Singleton_DoubleKey doubleKey = null;  
  11.       
  12.     private Singleton_DoubleKey (){}  
  13.       
  14.     public static Singleton_DoubleKey getInstance(){  
  15.         if( doubleKey == null ){    //①  
  16.             synchronized(Singleton_DoubleKey.class){    //②  
  17.                 if( doubleKey == null ){    //③  
  18.                     doubleKey = new Singleton_DoubleKey();  //④  
  19.                 }  
  20.             }  
  21.         }  
  22.         return doubleKey;  
  23.     }  
  24. }  

     说明:双锁机制的出现是为了解决前面同步问题和性能问题,看上面的代码,简单分析下确实是解决了多线程并行进来不会出现重复new对象,而且也实现了懒加载,但是当我们静下来并结合java虚拟机的类加载过程我们就会发现问题出来了,对于JVM加载类过程不熟悉的,这里我简单介绍下,熟悉的跳过这段(当然,既然你熟悉就自然会知道双锁的弊端了)。

jvm加载一个类大体分为三个步骤:

  1. 加载阶段:就是在硬盘上寻找java文件对应的class文件,并将class文件中的二进制数据加载到内存中,将其放在运行期数据区的方法区中去,然后在堆区创建一个java.lang.Class对象,用来封装在方法区内的数据结构;
  2. 连接阶段:这个阶段分为三个步骤,步骤一:验证,验证什么呢?当然是验证这个class文件里面的二进制数据是否符合java规范咯;步骤二:准备,为该类的静态变量分配内存空间,并将变量赋一个默认值,比如int的默认值为0;步骤三:解析,这个阶段就不好解释了,将符号引用转化为直接引用,涉及到指针,这里不做多的解释;
  3. 初始化阶段:当我们主动调用该类的时候,将该类的变量赋于正确的值(这里不要和第二阶段的准备混淆了),举个例子说明下两个区别,比如一个类里有private static int i = 5; 这个静态变量在"准备"阶段会被分配一个内存空间并且被赋予一个默认值0,当道到初始化阶段的时候会将这个变量赋予正确的值即5,了解了吧!

好了,上面大体介绍了jvm类加载过程,回到我们的双锁机制上来分析下问题出在了哪里?假如有两个并发线程a、b,a线程主动调用了静态方法getInstance(),这时开始加载和初始化该类的静态变量,b线程调用getInstance()并等待获得同步锁,当a线程初始化对象过程中,到了第二阶段即连接阶段的准备步骤时,静态变量doubleKey 被赋予了一个默认值,但是这时还没有进行初始化,这时当a线程释放锁后,b线程判断doubleKey != null,则直接返回了一个没有初始化的doubleKey 对象,问题就出现在这里了,b线程拿到的是一个被赋予了默认值但是未初始化的对象,刚刚可以通过锁的检索!

 

所以对于上面的几个模式还是推荐使用第一种,在jvm加载类的时候就初始化一个对象,也避免了同步问题。

举报

相关文章推荐

java设计模式之单例模式

欢迎使用Markdown编辑器写博客本Markdown编辑器使用StackEdit修改而来,用它写博客,将会带来全新的体验哦: Markdown和扩展Markdown简洁的语法 代码块高亮 图片链接和...

JAVA设计模式之单例模式

[size=large]概念:   java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例、饿汉式单例、登记式单例三种。   单例模式有以下特点:   1、单例类只能有一个实例。   2、单例类必须自己创建自己的唯一实例。   3、单例类必须给所有其他对象提供这一实例。   ...

程序员升职加薪指南!还缺一个“证”!

CSDN出品,立即查看!

【Java】设计模式:深入理解单例模式

什么是设计模式?简单的理解就是前人留下来的一些经验总结而已,然后把这些经验起了个名字叫Design Pattern,翻译过来就是设计模式,通过使用设计模式可以让我们的代码复用性更高,可维护性更高,让你...

JAVA设计模式学习7——单例模式

设计模式的创建模式中前面说了工厂模式,这里我们继续来讨论设计模式中另一个创建模式—单例模式。单例模式(Singleton)是指确保一个类有且仅有一个实例,而且自行实例化并向整个系统提供这个实例。这个类我们也称它为单例类。单例模式的使用在现实世界里很多,比如我们常见的打印机打印的作业队列,一个没打印完...

常用Java设计模式系列(1)- 单例模式

之前一段时间因为一些事情,挺长时间没有再写博客了,可是作为一个二十一世纪的好青年,怎么能半途而废呢,所以,从今天开始,我要继续把我写博客(尤其是技术博客)的传统延续下去,尽量做到每周都更新一篇博文,广...
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)