`
balan
  • 浏览: 68799 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java Singleton 实用教程(附源码)

阅读更多

作者:Balan

什么是Java Singleton

Singleton是独身、单独一个的意思,发音是KK: [ ],DJ: [ ]。

Java Singleton是指在特定系统范围内只能实例化一次的Java类,并且为该类提供一个全局的访问点。很多地方,Singleton 当作模式来讲。Java Singleton 常用于代表特定系统范围内需要保持唯一性的组件。例如一个蜜蜂王国系统内,蜂王类的实例只能有一个。

实现Java Singleton的方案

Java Singleton是指在特定系统范围内只能实例化一次的Java类,如何理解特定系统范围?按照需求和环境定义系统范围,关注在特定系统范围内单一实例的需求:

系统范围和环境定义 方案编号
框架容器内 A
单一JVM中、单一类加载器加载类 B、C、D
单一JVM、不同类加载器加载相同类  
系统跨多个JVM  

A

提供实例管理容器的第三方框架,例如Spring IOC容器,可以通过配置保证实例在容器内的唯一性。这些被外部容器管理的类,能在某个容器范围内达到Singleton的效果,不一定禁止自身在容器外部范围生成多个实例。 这种方案可以看作是一种局部的单例解决方案。

B

代码示范如下

B

C

C

D

有时候类的实例化开销较为昂贵,有时候类的实例化要用到系统运行时的动态数据做参数等等,在上述情形,静态成员变量需要延迟初始化。程序员中间流传较广的一种形式是:

D_01

这种写法最大的问题是getInstance()方法被多个线程竞争使用的时候,可能会产生多个实例,违反了单例设计的初衷。如果多个实例的风险(Singleton失败)不会引起您的系统异常,比如实例存放的是无状态的数据、实例是轻量级的,您可以坚持这种写法。

当然还有改进的方法,一般是在该方法前加上“synchronized”关键字:

D_02

这种作法的副作用就是影响性能。

双检查锁(Double-Checked Locking)是在多线程环境下实现延迟初始化的有效方式(如C++),不幸的是,对大多数JVM是无效的。有一篇文章解释的很深入:http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

其他方案

单一JVM、不同类加载器加载相同类或跨多个JVM的情形,要保证Java Singleton不失败,我还没找到恰当的方法。

有些人认为单例的需求不仅仅是来自某些组件自身的唯一特性,还来自对创建并维护多个对象产生消耗的无法忍受、来自对性能的追求。如果出于降低消耗和提高性能的目的,很多无状态的类(类的所有实例天然是始终相同的),即便面临单一JVM、不同类加载器加载相同类或跨多个JVM的情形,也可以采用上述的Singleton实现方式,可以尽量减少实例的数量。

当Java Singleton遇到反序列化

一个序列化的实例,每次反序列化的时候都会产生一个新的实例。Singleton也不例外。

我们看看一个例子:

001

进行序列化测试

public static void main(String[] args) throws Exception{
         //序列化
          ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("E:\\kingBedroom.obj"));
          King king_1 = King.INSTANCE;         
          objectOutputStream.writeObject(king_1);
          objectOutputStream.close();
          //反序列化
          ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("E:\\kingBedroom.obj"));
          King king_2 = (King)objectInputStream.readObject();
          objectInputStream.close();
          //比较是否原来的实例
          System.out.println(king_1==king_2);

    }

结果是false

解决方法是为King类增加readResolve()方法:

private Object readResolve(){
        return INSTANCE;
    }

反序列化之后新创建的对象会先调用此方法,该方法返回的对象引用被返回,取代了新创建的对象。本质上,该方法忽略了新建对象,仍然返回类初始化时创建的那个实例。

参考资料:

  1. “使用私有构造函数强化singleton属性”,《Effective Java中文版 》 Joshua Bloch 著,潘爱民 译
  2.  深入Java中的Singleton模式与延缓初始化 ,dev2dev.bea.com.cn论坛  作者beastiedog_bea
  • singleton.zip (5.1 KB)
  • 描述: 附件中是本文样例的源代码工程包,使用Eclipse导入即可。
  • 下载次数: 76
3
1
分享到:
评论

相关推荐

    java源码

    在“图书管理系统”这个项目中,我们将会探讨如何使用Java来实现一个实用的图书管理软件。这个系统可能包含了图书的录入、查询、借阅、归还等基本功能,旨在帮助图书馆或书店更有效地进行图书的管理工作。 首先,...

    整理的23设计模式java源码

    这些源码可以作为学习和理解设计模式的实用参考,你可以通过阅读和分析这些代码,加深对每种模式的理解,提升你的编程技能。同时,这些模式在实际项目中都有广泛的应用,熟练掌握它们能帮助你编写出更加高效、易于...

    java设计模式程序源代码 张跃平 耿祥义

    张跃平和耿祥义作为知名的技术专家,他们的著作深入浅出地解释了这些模式,提供了实用的源代码示例,旨在帮助开发者理解和应用这些设计原则。 首先,设计模式分为三大类:创建型、结构型和行为型。创建型模式关注...

    SimpleTimeKeeper-源码.rar

    2. **设计模式**:在源码中,可能会使用到单例模式(Singleton)来确保全局只有一个时间管理实例,或者工厂模式(Factory)来创建不同的计时器类型。观察者模式(Observer)可能用于更新界面显示,当计时状态改变时...

    commons-lang-3-3.1 jar包和源码包

    通过源码包,开发者可以直接查看和学习这些工具类的实现细节,理解其工作原理,这对于学习和提高Java编程技能非常有帮助。此外,对于需要定制或扩展已有功能的开发者,源码可以提供宝贵的参考和灵感。 总之,Apache...

    Android应用源码之源码捏苍蝇.zip

    源码中可能包含多个Java类,这些类通常会继承自Android的基类,例如`Activity`、`Service`、`BroadcastReceiver`等。在游戏开发中,主活动(MainActivity)通常是游戏的入口点,它负责初始化游戏界面,加载资源,并...

    java电话本源代码

    通过学习这个Java电话本源代码,你可以深入了解Java的基础语法、面向对象编程思想、GUI编程技巧,以及文件操作和异常处理等实用技能。对于想要提升Java编程能力的初学者来说,这是一个很好的实践项目。

    C++与java设计模式分开详解

    创建型模式涉及对象的创建,如单例模式(Singleton)、工厂模式(Factory)和抽象工厂模式(Abstract Factory)等,它们提供了灵活且控制性强的对象创建方式。结构型模式关注如何组合类和对象以构建更大的结构,例如...

    Java_final_ToDoList

    它展示了如何利用Java的核心特性和设计模式来构建一个实用的桌面应用。这个项目主要涉及到以下几个核心知识点: 1. **Java基础**:项目的基石是Java编程语言的基础知识,包括类、对象、封装、继承、多态等面向对象...

    用enum实现单例模式的方法来读取配置文件

    在Java编程中,单例模式是一种常用的创建型设计模式,它保证了类只有一个实例,并提供一个全局访问点。单例模式常用于管理共享资源,如配置文件的读取。本篇将详细介绍如何利用枚举(enum)来实现单例模式,并结合`...

    基于Android Studio游戏开发 飞飞机大战小游戏源码,可暂停、继续游戏、开关背景音乐等功能。

    本文将深入探讨如何基于Android Studio开发一款名为“飞飞机大战”的小游戏,该游戏具备暂停、继续游戏以及开关背景音乐等实用功能。 首先,Android Studio为开发者提供了丰富的工具和资源,使得游戏开发变得相对...

    设计模式源码

    JAVA的多线程特性使得状态模式和观察者模式在并发编程中尤为实用。 对于压缩包中的“behavioral”文件夹,我们可以推测其包含的是关于行为型设计模式的源码示例。这些模式如命令模式、迭代器模式、中介者模式等,都...

    Java 设计模式

    在Java中,设计模式的应用广泛且实用,例如,Spring框架就大量使用了工厂模式、单例模式、代理模式等。理解并熟练运用设计模式,可以帮助我们编写出更符合设计原则(如开闭原则、依赖倒置原则等)的代码,提高代码的...

    单例模式介绍

    在Android开发中,单例模式应用广泛,尤其在管理全局资源、提供公共服务或优化性能时非常实用。下面我们将详细介绍六种常见的单例模式,并探讨在Android环境下如何应对反序列化安全问题。 1. 饿汉式单例(Static ...

    nicommons-java:Java 的可重用模式

    "nicommons-java" 是一个基于 Java 的开源项目,它提供了可重用的代码模式和实用工具类,旨在简化常见的编程任务,提高开发效率。这个项目的核心理念是封装常用功能,减少代码重复,遵循良好的软件设计原则,如单一...

    java设计模式

    这篇博客文章可能是对Java设计模式的一种深入探讨,通过作者Vbtboy在ITEYE上的分享,我们可以期待获取到一些实用的设计模式应用和理解。 首先,设计模式分为三大类:创建型、结构型和行为型模式。创建型模式关注...

Global site tag (gtag.js) - Google Analytics