Java Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。 使用Singleton的好处还在于可以节省内存,因为它限制了实例的个数,有利于Java垃圾回收(garbage collection)。

我们在浏览BBS、SNS网站的时候,常常会看到“当前在线人数”这样的一项内容。对于这样的一项功能,我们通常的做法是把当前的在线人数存放到一个内存、文件或者数据库中,每次用户登录的时候,就会马上从内存、文件或者数据库中取出,在其基础上加1后,作为当前的在线人数进行显示,然后再把它保存回内存、文件或者数据库里,这样后续登录的用户看到的就是更新后的当前在线人数;同样的道理,当用户退出后,当前在线人数进行减1的工作。所以,对于这样的一个需求,我们按照面向对象的设计思想,可以把它抽象为“在线计数器”这样一个对象。

网站代码中凡是用到计数器的地方,只要new一个计数器对象,然后就可以获取、保存、增加或者减少在线人数的数量。不过,我们的代码实际的使用效果并不好。假如有多个用户同时登录,那么在这个时刻,通过计数器取到的在线人数是相同的,于是他们使用各自的计数器加1后存入文件或者数据库。这样操作后续登陆的用户得到的在线人数,与实际的在线人数并不一致。所以,把这个计数器设计为一个全局对象,所有人都共用同一份数据,就可以避免类似的问题,这就是我们所说的单例模式的其中的一种应用。

单例模式能够保证一个类仅有唯一的实例,并提供一个全局访问点。

我们是不是可以通过一个全局变量来实现单例模式的要求呢?我们只要仔细地想想看,全局变量确实可以提供一个全局访问点,但是它不能防止别人实例化多个对象。通过外部程序来控制的对象的产生的个数,势必会系统的增加管理成本,增大模块之间的耦合度。所以,最好的解决办法就是让类自己负责保存它的唯一实例,并且让这个类保证不会产生第二个实例,同时提供一个让外部对象访问该实例的方法。自己的事情自己办,而不是由别人代办,这非常符合面向对象的封装原则。

单例模式主要有3个特点,:

1、单例类确保自己只有一个实例。

2、单例类必须自己创建自己的实例。

3、单例类必须为其他对象提供唯一的实例。

单例模式的实现方式:懒汉单例类和饿汉单例类

单例模式的实现有多种方法,常见的就有懒汉式单例类和饿汉式单例类。我们前面介绍的实现方法就属于懒汉式单例类。

· 懒汉式单例类

对于懒汉模式,我们可以这样理解:该单例类非常懒,只有在自身需要的时候才会行动,从来不知道及早做好准备。它在需要对象的时候,才判断是否已有对象,如果没有就立即创建一个对象,然后返回,如果已有对象就不再创建,立即返回。

懒汉模式只在外部对象第一次请求实例的时候才去创建。

· 饿汉式单例

对于饿汉模式,我们可以这样理解:该单例类非常饿,迫切需要吃东西,所以它在类加载的时候就立即创建对象。

我们对比一下懒汉模式和饿汉模式的优缺点:

懒汉模式,它的特点是运行时获得对象的速度比较慢,但加载类的时候比较快。它在整个应用的生命周期只有一部分时间在占用资源。

饿汉模式,它的特点是加载类的时候比较慢,但运行时获得对象的速度比较快。它从加载到应用结束会一直占用资源。

这两种模式对于初始化较快,占用资源少的轻量级对象来说,没有多大的性能差异,选择懒汉式还是饿汉式都没有问题。但是对于初始化慢,占用资源多的重量级对象来说,就会有比较明显的差别了。所以,对重量级对象应用饿汉模式,类加载时速度慢,但运行时速度快;懒汉模式则与之相反,类加载时速度快,但运行时第一次获得对象的速度慢。

从用户体验的角度来说,我们应该首选饿汉模式。我们愿意等待某个程序花较长的时间初始化,却不喜欢在程序运行时等待太久,给人一种反应迟钝的感觉,所以对于有重量级对象参与的单例模式,我们推荐使用饿汉模式。

而对于初始化较快的轻量级对象来说,选用哪种方法都可以。如果一个应用中使用了大量单例模式,我们就应该权衡两种方法了。轻量级对象的单例采用懒汉模式,减轻加载时的负担,缩短加载时间,提高加载效率;同时由于是轻量级对象,把这些对象的创建放在使用时进行,实际就是把创建单例对象所消耗的时间分摊到整个应用中去了,对于整个应用的运行效率没有太大影响。

什么情况下使用单例模式

单例模式也是一种比较常见的设计模式,它到底能带给我们什么好处呢?其实无非是三个方面的作用:

第一、控制资源的使用,通过线程同步来控制资源的并发访问;

第二、控制实例产生的数量,达到节约资源的目的。

第三、作为通信媒介使用,也就是数据共享,它可以在不建立直接关联的条件下,让多个不相关的两个线程或者进程之间实现通信。

比如,数据库连接池的设计一般采用单例模式,数据库连接是一种数据库资源。软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是非常昂贵的。当然,使用数据库连接池还有很多其它的好处,可以屏蔽不同数据数据库之间的差异,实现系统对数据库的低度耦合,也可以被多个系统同时使用,具有高可复用性,还能方便对数据库连接的管理等等。数据库连接池属于重量级资源,一个应用中只需要保留一份即可,既节省了资源又方便管理。所以数据库连接池采用单例模式进行设计会是一个非常好的选择。

在我们日常使用的在Windows中也有不少单例模式设计的组件,象常用的文件管理器。由于Windows操作系统是一个典型的多进程多线程系统,那么在创建或者删除某个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象。采用单例模式设计的文件管理器就可以完美的解决这个问题,所有的文件操作都必须通过唯一的实例进行,这样就不会产生混乱的现象。

再比如,每台计算机可以有若干个打印机,如果每一个进程或者线程都独立地使用打印机资源的话,那么我们打印出来的结果就有可能既包含这个打印任务的一部分,又包含另外一个打印任务的一部分。所以,大多数的操作系统最终为打印任务设计了一个单例模式的假脱机服务Printer Spooler,所有的打印任务都需要通过假脱机服务进行。

实际上,配置信息类、管理类、控制类、门面类、代理类通常被设计为单例类。像Java的Struts、Spring框架,.Net的Spring.Net框架,以及Php的Zend框架都大量使用了单例模式。

Java中用单例模式有什么好处?的更多相关文章

  1. 【转】Java中用单例模式有什么好处

    Java Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在. 使用Singleton的好处还在于可以节省内存,因为它限制了实例的个数,有利于Java垃圾回收( ...

  2. Java学习-----单例模式

    一.问题引入 偶然想想到的如果把Java的构造方法弄成private,那里面的成员属性是不是只有通过static来访问呢:如果构造方法是private的话,那么有什么好处呢:如果构造方法是privat ...

  3. Java 设计模式 —— 单例模式

    1. 概念: 单例模式是一种常用的软件设计模式.核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源.如果 ...

  4. Java中用正则表达式判断日期格式是否正确

    1.Java中用正则表达式判断日期格式是否正确 DateType.java: /** * @Title:DateType.java * @Package:com.you.dao * @Descript ...

  5. Java中用正则表达式找出数字

    Java中用正则表达式找出数字 1.题目    String str = "fjd789klsd908434jk#$$%%^38488545",从中找出78990843438488 ...

  6. java设计模式单例模式 ----懒汉式与饿汉式的区别

    常用的五种单例模式实现方式 ——主要: 1.饿汉式(线程安全,调用率高,但是,不能延迟加载.) 2.懒汉式(线程安全,调用效率不高,可以延时加载.) ——其他: 1.双重检测锁式(由于JVM底层内部模 ...

  7. 折叠代码块 C#中用 #region和#endregion java中用 //region和//endregion

    折叠代码块 C#中用 #region和#endregion   java中用 //region和//endregion

  8. java泛型的作用和好处

    转载于:https://blog.csdn.net/u012760183/article/details/52092692 之前参加面试的时候遇到面试官问泛型的作用,只是说了大概自己的理解, 在此转载 ...

  9. Java设计模式 - 单例模式 (懒汉方式和饿汉方式)

    概念: Java中单例模式是一种常见的设计模式,单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. 单例模式的写法有好几种,这 ...

随机推荐

  1. Python中self的用法

    在Python类中规定,函数的第一个参数是实例对象本身,并且约定俗成,把其名字写为self.其作用相当于java中的this,表示当前类的对象,可以调用当前类中的属性和方法. 在python中,类是通 ...

  2. 关于html的基本知识

    先上基本介绍图 HTML 简介 超文本标记语言 Hyper Text Markup Language 什么是标签(大多数标签) 尖括号包围.成对出现 开始标签,结束标签 元素 编辑器 HBuilder ...

  3. Codeforces 599D:Spongebob and Squares

    D. Spongebob and Squares time limit per test 2 seconds memory limit per test 256 megabytes input sta ...

  4. redis 高级学习和应用场景

    redis 高级学习 1.redis 复制 2.redis 集群 3.哨兵机制 4.spring 与哨兵结合 5.数据恢复与转移 6.redis 的阻塞分析 redis 实战 1. 数据缓存(热点数据 ...

  5. 【PAT甲级】1028 List Sorting (25 分)

    题意: 输入一个正整数N(<=100000)和C(C属于{1,2,3}),接下来输入N行,每行包括学生的六位学号(习惯用string输入,因为可能有前导零),名字和成绩(正整数).输出排序后的信 ...

  6. HTML5模板引擎 Thymeleaf 教程(转)

    原文:http://www.open-open.com/lib/view/open1383622135586.html Thymeleaf是一个XML/XHTML/HTML5模板引擎,可用于Web与非 ...

  7. Django 学习 之ORM多表操作

    一.创建模型 1.模型关系整理 创建一对一的关系:OneToOne("要绑定关系的表名") 创建一对多的关系:ForeignKey("要绑定关系的表名") 创建 ...

  8. css之元素浮动

    什么时候用浮动——块级元素一行显示就使用浮动 浮动的特点——让元素脱标不占位置 什么时候清除浮动——父元素没有设置高度:父元素中所有的子元素都设置浮动 清除浮动的方法(掌握): 1.额外标签清除浮动 ...

  9. PLSQL设置显示的字符集及设置

    一.关于PLSQL无法正确显示中文 刚才下载安装了PLSQL Developer 9.0.0.1601 汉化绿色版,执行SQL查询语句,发现显示的数据中只要有中文都会以?表示.经过网上查询得知这是客户 ...

  10. Python学习第四课——基本数据类型一之int and str

    1.数字(int) - int() 方法 # 定义 a1=123 a2=456 #功能1:将字符串转换为数字 #例子1: a = " print(type(a)) # type()为查看类型 ...