[关闭]
@frank-shaw 2015-10-29T10:35:34.000000Z 字数 1276 阅读 1872

单例模式分析与代码

java.基础知识


定义

单例设计模式指的是某个类只能被实例化一次,用来表示全局或系统范围的组件。单例模式常用于日记记录、工厂、窗口管理器和平台组件管理等。

如何保证对象唯一性呢?

1.不允许其他程序用new创建该类对象。
2.在该类创建一个本类实例。
3.对外提供一个方法让其他程序可以获取该对象。

步骤:

1.私有化该类构造函数。
2.通过new在本类中创建一个本类对象。
3.定义一个公有的方法,将创建的对象返回。

单例的实现

单例的实现有饿汉式、懒汉式两种。具体请看代码实现:

饿汉式:

所谓饿汉饿汉,就是担心饿死了,在一开始就准备好实例化对象,生怕以后就再也吃不到了。

  1. class Single{
  2. //饿汉,在一开始就已经创建了实例化对象,等待调用即可
  3. private static Single s1 = new Single();
  4. //私有化初始化函数,让其他函数无法调用其初始化函数
  5. private Single(){}
  6. //暴露一个外在函数接口,允许他人通过此函数调用唯一实例
  7. public static Single getInstance(){
  8. return s1;
  9. }
  10. }

通过分析可以知道,饿汉式不存在线程安全问题,非常保险。只是很多时候不需要一开始就实例化好对象,在别人调用的时候再来实例化也不迟。

懒汉式

所谓懒汉,就是懒,当你需要这个对象的时候,我才来考虑初始化,并且调用这个唯一的实例给你。在考虑了线程安全的前提下,可以协程如下代码。

  1. class Single{
  2. private static s1 = null;
  3. //私有化初始化函数,让其他函数无法调用其初始化函数
  4. private Single(){}
  5. //暴露一个外在函数接口,允许他人通过此函数调用唯一实例
  6. public static Single getInstance(){
  7. if(s1 == null){
  8. //同步代码块,线程安全用
  9. synchronized(Single.class){
  10. if(s1 == null){
  11. s1 = new Single();
  12. }
  13. }
  14. }
  15. return s1;
  16. }
  17. }

以上代码有值得学习的地方:1.加入同步代码块是为了解决线程安全问题,这无可厚非;2.加入双重判断是为了解决效率问题:当第一个线程已经实例化该对象之后,之后的线程再也不用判断同步锁。(原来如此!)

今天看了鹏哥介绍给我的java公众号,里面看到了同样的一个懒汉式的实现,不需要同步锁即可实现线程安全,它使用的是内部类静态变量的方法。请看:

  1. class Single{
  2. //私有化初始化函数,让其他函数无法调用其初始化函数
  3. private Single(){}
  4. //注意类的使用范围
  5. private static class SingleHolder{
  6. private static final Single s1 = new Single();
  7. }
  8. public static Single getInstance(){
  9. return SingleHolder.s1;
  10. }
  11. }

在初次调用getInstance()方法的时候,会将内部类SingleHolder放入到方法区中,以后不会再引入相同的类,每一次都是直接调用相同的Single实例。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注