前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >剑指offer第二版(Java最优解)---实现单例模式(3种)

剑指offer第二版(Java最优解)---实现单例模式(3种)

作者头像
葆宁
发布2019-04-18 15:09:19
6090
发布2019-04-18 15:09:19
举报
文章被收录于专栏:FREE SOLOFREE SOLO

单例模式的定义

单例模式最初的定义出现于《设计模式》(艾迪生维斯理,1994):“保证一个类仅有一个实例,并提供一个访问它的全局访问点。”   另一个常见的定义是:一个类只有一个实例,并且自行实例化向整个系统提供。   这两句话的意思就是,当我们需要用到某个实例的时候,我们无需进行其它多余操作,而是直接通过某个接口获取到它的实例,并且这个实例在整个系统中保证唯一。   举个简单的例子:我们在平时使用电脑时,我们希望点击“设置”按钮,就可以直接访问设置,而且要求设置在整个系统中是唯一的(这是废话),电脑的设置在这里就是一个单例。   我们通过定义,得出完成单例模式需要满足下面两个条件: 1. 生成类的实例要唯一。也就是生成代码只能执行一次,“阻止”所有想要生成新对象的操作;   2. 生成实例的方法必须是全局方法(也就是静态)。原因是非静态方法必须通过实例进行调用,如果已经有了实例,我们还需要生成实例的方法干什么呢?

饿汉式

在这里插入图片描述
在这里插入图片描述

优点:线程安全,代码简单;   缺点:不能延迟加载,系统性能会有所降低。

懒汉式

在这里插入图片描述
在这里插入图片描述

双重判断被称为双重检查加锁(DCL,double check lock)。   其中用了两个if() 判断,第一个if 先判断singleton 是否为null :如果不为null ,说明singleton 已经被初始化了,直接返回singleton ;   如果singleton 为null ,说明singleton 还没有被初始化,这样才会去执行synchronized 修饰的代码块内容,只在其初始化的时候调用一次。这样的设计既能保证只产生一个实例,并且只在初始化的时候加同步锁,也实现了延迟加载。

对于synchronized 关键字,当一个线程访问对象的一个synchronized(xx.class) 同步代码块时,另一个线程仍然可以访问该对象中的非synchronized(xx.class) 同步代码块。  volatile 关键字禁止指令重排序的做法是在对被其修饰的变量进行操作时,增加一个内存屏障(Memory Barrier或Memory Fence,指重排序时不能把后面的指令重排序到内存屏障之前的的位置)用以保证一致性。这样我们就解决了指令重排序的问题。

优点:能延迟加载,也能保证线程安全;

缺点:代码较复杂。

延迟初始化占位(Holder)类模式(推荐)

在这里插入图片描述
在这里插入图片描述

这种方式成为延迟初始化占位(Holder)类模式。该模式引入了一个内部静态类(占位类),内部静态类只有在调用时才会加载,既保证了Ex02Singleton 实例的延迟初始化,又保证了实例的唯一性。是一种提前初始化(饿汉式)和延迟初始化(饱汉式)的综合模式,推荐使用这种操作。

这种方法基于在懒汉模式中提出的,JVM在类的初始化阶段给出的线程安全性保证,将singleton 的实例化操作放置到一个静态内部类中,在第一次调用getInstance() 方法时,JVM才会去加载InstanceHolder 类,同时初始化singleton 实例,因此,即使我们不采取任何同步策略,getInstance() 方法也是线程安全的。 优点:能延迟加载,也能保证线程安全。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年04月14日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 单例模式的定义
  • 饿汉式
  • 懒汉式
  • 延迟初始化占位(Holder)类模式(推荐)
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档