`
fjjiaboming
  • 浏览: 32343 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

单例模式代码实现与解析,java实现

阅读更多
Singleton模式和它的变体Double-Checked Locking模式比较简单,而且非常常用.

按照<设计模式>一书 ,singleton 意图:保证一个类有且仅有一个实例,并对外提供一个访问它的全局访问点.
其具体的关键特征和工作原理,不在此文表述,可以参看<Design Patterns Explained>一书.

以下逐步提供代码实现:

代码1, 最经典的实现:  把class中所有的methods和fields/status全部声明为static,
然后初始化还可以用static关键字,显示的初始化.
(有兴趣的请参见<Thinking.In.Java.4th.Edition>一书中的节Explicit static initialization)

代码1:
public class StaticSingleton {
  public static int count =0;
  private static String name =null;  
  static {
    name  = "singleton";
  }

  public static String getName() {
    return name;
  }

  public static void setName(String name) {
    StaticSingleton.name = name;
  }
}

假设该StaticSingleton 有许多的methods和fields/status,那么我们的代码就有所多static关键字了.
这样对于声明的methods和fields/status都要打上static关键字.似乎有点累,
书写代码后,看来似乎有点不美观,
且对于JDK6开始,StaticSingleton 对外的引用全要写成StaticSingleton.A ,或StaticSingleton.getA()之类的,
让StaticSingleton 的局外使用不够简洁.
那么产生代码2.

代码2: Eager式的Singleton (实际上多线程不可行)
public class EagerSingleton1 {
  private static EagerSingleton1 instance;
  private EagerSingleton1() {
  }
  public static EagerSingleton1 getInstance() {
    if( instance == null ) instance = new EagerSingleton1();
    return instance;
  }
}

带父类的.
示例:
public class EagerSingleton1 extends SuperSingleton {
  private static SuperSingleton instance;
  private EagerSingleton1() {
  }
  public static SuperSingleton getInstance() {
    if( instance == null ) instance = new EagerSingleton1();
    return instance;
  }
}

代码2, 只能用于单线程情况,假设多线程情况下,那么就会出现问题.
如两个线程都执行EagerSingleton1 的new 操作,那后果就可以想象一下.
因此在多线程下我们加入线程同步代码像 代码4 或 代码3.

代码3:
public class EagerSingleton {
  //是否带final,视情况而定.
  private static EagerSingleton instance = new EagerSingleton();
  private EagerSingleton() {
  }
  public static EagerSingleton getInstance() {       
    return instance;
  }  
}

带父类的代码(略).


代码4.  (针对JAVA,多线程还是不可行,原因JAVA编译器本身优化工作)
针对代码2解决方法:在检查null之后进行同步(doSync()),然后再检查一次,确保实例尚未创建.
这就称为Double-Checked Locking模式.
实际上这是C++转换成JAVA的.

代码4: 可以带父类的
public class LazySingleton extends SuperSingleton {
  // 是否带final,视情况而定.
  private static volatile LazySingleton instance = null;
  private LazySingleton() {
  }
  public static SuperSingleton getInstance() {
    if( instance == null ) {
      synchronized (LazySingleton.class) {
        if( instance == null ) {
          instance = new LazySingleton();
        }
      }
    }
    return instance;
  }
  //private synchronized static void doSync() {
  //  if( instance == null ) instance = new LazySingleton();
  //}
}

根据Java的语言规范,上面的代码是不可靠的。
出现上述问题, 最重要的2个原因如下:
1, 编译器优化了程序指令, 以加快CPU处理速度.
2, 多核CPU动态调整指令顺序, 以加快并行运算能力.
问题出现的顺序:
1, 线程A, 发现对象未实例化, 准备开始实例化
2, 由于编译器优化了程序指令, 允许对象在构造函数未调用完前, 将 共享变量的引用指向 部分构造的对象, 虽然对象未完全实例化, 但已经不为null了.
3, 线程B, 发现部分构造的对象已不是null, 则直接返回了该对象.
不过, 一些著名的开源框架, 包括jive,lenya等也都在使用DCL模式, 且未见一些极端异常.
说明, DCL失效问题的出现率还是比较低的.



利用JAVA ClassLoader ,JRE自身特点,产生代码5.
(有兴趣的可以看看IBM和sun网写的java classLoader文章和有关类加载顺序)

代码5: 可以带父类的 // 会生成文件Singleton.class和Singleton$Instance.class
public class Singleton extends SuperSingleton {
  //内部类,将只被装载一次. 
  private static class Instance {
    //final关键字
    static final SuperSingleton instance = new Singleton();
  }
  private Singleton() {
  }
  public static SuperSingleton getInstance() {
    return Instance.instance;
  }
  //暂未使用Singleton instance
  private static Singleton instance;
  public void doA() {
  }
  public void doB() {
  }

   //危险代码.
  protected void finalize(){
   //置空操作
  }
}

代码5, 是对于单线程或多线程都是可行的.
更符合类间关系的原则,对于对象A,A要么只创建B类,要么只使用B类的方法,不要二者兼之.
然后试试对代码5的使用感受吧.

注:另外针对从代码2到代码5,在ECLIPSE下是可以自己创建代码模板,供生成代码2到代码5.
在此不提供,让大家自己熟悉代码.
模板位置:eclipse->windows->preferrence->java->editors->templates->...
最后快捷键:ALT+/


参考资料:
1. book:  design pattern explains.
2. books and papers :  java memory model
3. java class loader
http://java.sun.com/developer/technicalArticles/Networking/classloaders/
http://download.oracle.com/javase/tutorial/ext/basics/load.html
http://www.ibm.com/developerworks/cn/java/j-lo-classloader/?ca=drs-tp4608
https://docs.google.com/viewer?a=v&q=cache:XhllCyQFTS0J:www.freejavaguide.com/jcl.pdf+java+classloader+ibm&hl=zh-CN&pid=bl&srcid=ADGEESiOaJjb2W-ilYRra4XOQEV4xbG1risXhRXdxtY0qYnhryvduOsLQapuQDdh1-A8frGy0cAqGNMV4vt8x-q_TLAoqgOKWpA1dlbn-6l_Jm3z2I6AvOLiXCztNafc_dx72C1hLzz0&sig=AHIEtbStlkg0vB89MsPd_YQQgHnpcrKn7A&pli=1
分享到:
评论
1 楼 fjjiaboming 2018-01-23  
有找工作的技术大牛(类似阿里P7 P8 P9), 请私信给我或者邮件至: 534439207@qq.com

相关推荐

    java单例五种实现模式解析

    主要介绍了java单例五种实现模式解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    Java设计模式 pdf 示例代码 刘伟

    它的讲解思路为:模式动机-&gt;模式定义-&gt;模式结构-&gt;模式分析(即原理)-&gt;实例解析-&gt;模式优缺点-&gt;模式使用场景-&gt;模式应用-&gt;模式扩展。采用图文+文字+实例的方式,让读者不仅知其然,还能知其所以然。读后有种豁然开朗的...

    Java实现单例设计模式方法解析

    主要介绍了Java实现单例设计模式方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    Java设计模式单例模式(Singleton)用法解析

    主要介绍了Java设计模式单例模式(Singleton)用法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    10道Java面试必备的设计模式面试题!.pdf

    本文将对 Java 设计模式面试题进行解析,涵盖了单例模式、观察者模式、工厂模式、装饰器模式等常见设计模式,并对每个模式的定义、应用场景和实现方式进行了详细的解释。 一、单例模式(Singleton pattern) 单例...

    10道Java面试必备的设计模式面试题

    在本文中,我们将对 10 道 Java 面试必备的设计模式面试题进行详细的解析,涵盖了单例模式、观察者模式、工厂模式、装饰器模式等多种设计模式。 1. JDK 中常用的设计模式 在 JDK 中,有多种常用的设计模式,例如...

    Java实验1代码.doc

    本专栏主要为Java程序设计(基础)实验报告和Java程序设计(进阶)...进阶篇有反射、泛型、注解、网络编程、多线程、序列化、数据库、Servlet、JSP、XML解析、单例模式与枚举。本专栏主要为Java入门者提供实验参考。

    实验5 JAVA常用类.doc

    本专栏主要为Java程序设计(基础)实验报告和Java程序设计(进阶)...进阶篇有反射、泛型、注解、网络编程、多线程、序列化、数据库、Servlet、JSP、XML解析、单例模式与枚举。本专栏主要为Java入门者提供实验参考。

    java中的设计模式,主要的设计模式

    单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式 适配器模式、装饰者模式、代理模式、外观模式、桥接模式、组合模式、享元模式观察者模式、策略模式、模板模式、责任链模式、解析器模式、迭代子模式 ...

    2022年最新java面试题技术面试.docx

    单例模式是一种创建型模式,确保一个类只有一个实例,并提供一个全局访问点。例如,数据库连接、在线人数记录等。单例模式节省资源,控制了实例对象的个数,并有助于 GC 回收。 b) 方略模式: 策略模式是一种行为...

    基于Java实现的秒杀+shiro权限+信息采集等系统的实现源码

    秒杀项目练习 :seckill 该项目总体架构: Maven + SSM 日志: slf4j + logback 数据库相关:Mysql + c3p0 权限控制项目练习:springboot-shiro ...配置模块:单例模式,dom4j解析xml,IOC控制反转

    74个java面试题,只有题目没有答案

    * 如何在 Java 中实现单例模式?使用静态变量和同步机制实现单例模式。 16. Java GC * Java 中什么是 GC?GC(Garbage Collector)是 Java 的垃圾回收机制。 * 如何进行垃圾回收?使用 System.gc() 方法请求垃圾...

    Java-Programmer-Practice:Java工程师成长之路,包含JDK源码解析、Java并发编程、JVM实例解析、Spring全家桶、Spring Cloud以及各类中间件代码实例与教程。欢迎fork、star

    单例模式(饿汉式、懒汉式) 4. Linux的基础知识 Linux下的进程 Linux定时任务调度 Linux的七个运行级别 Linux进程启动顺序 深入理解Linux下的守护进程 理解Linux配置文件 下一阶段更新计划 增加JDK源码的注释 + ...

    5-java进阶-枚举与注解1

    * 实现单例模式。 * 实现策略模式。 注解 注解是 Java 语言中的一种元数据,用于提供某些信息给编译器或 runtime 环境。注解可以用来生成文档、格式检查、跟踪代码依赖性等。 注解的定义 在 Java 中,注解是使用...

    java核心面试技术点

    线程 单例模式下的线程安全http://blog.sina.com.cn/s/blog_75247c770100yxpb.html map集合 集合数据结构及方法的使用 多线程 线程进程 线程状态 线程状态的改变 sql :临时表、游标、存贮过程、触发机制...

    day020-继承加强和设计模式代码和笔记.rar

    本地代码实现的类加载器,它负责将 &lt;JAVA_HOME&gt;/lib下面的核心类库 或 -Xbootclasspath选项指定的jar包等 虚拟机识别的类库 加载到内存中。 由于引导类加载器涉及到虚拟机本地实现细节,开发者...

    3. 工厂模式1

    使用Map的工厂函数同时也是一个单例模式的应用。相较于在条件语句中创建实例,该方法更节省内存空间。 工厂模式 工厂模式实际上是对简单工厂模式的进一步封装,其目的在于将复杂类的创建从工厂类中剥离出去,并...

    java面试题

    如何控制两种框架中的单例模式? 74 73. Spring 75 73.1. Spring 简介 75 73.2. 为什么要用Spring? 76 73.3. spring工作机制或工作原理 76 73.4. Spring是什么?根据你的理解详细谈谈你的见解。 76 73.5. 项目中如何...

    java核心面试

    线程 单例模式下的线程安全http://blog.sina.com.cn/s/blog_75247c770100yxpb.html map集合 集合数据结构及方法的使用 多线程 线程进程 线程状态 线程状态的改变 sql :临时表、游标、存贮过程、触发机制...

    2021年简单的软件开发面试问题.docx

    在 Java 中,可以使用各种设计模式和技术来实现不同的功能,例如单例模式、工厂模式、代理模式等。单例模式是一种常见的设计模式,通过单例模式可以保证一个类只有一个实例,例如: public class Singleton { ...

Global site tag (gtag.js) - Google Analytics