深度认识单例模式;在Android源码中的应用

本文详细介绍了单例模式的定义、应用场景、九种常见写法及其优缺点,特别关注于线程安全和懒加载策略,以及在Android开发中的实际运用。同时,作者强调了系统化学习的重要性。
摘要由CSDN通过智能技术生成

这些可能大多数人都一知半解。今天就让我们大家一起来扒光单例模式的外衣,有深度的认识一下单例模式。

通过这篇文章你能学到什么

(建议你可以带着问题去学习)

  1. 单例模式的定义

  2. 单例模式在Android源码中的应用

  3. 单例模式的九种写法以及优劣对比

  4. 单例模式的使用场景

  5. 单例模式存在的缺点

  6. 接下来我们就一起进入今天的学习了

单例模式的定义

在学单例模式之前,我想大家都会自己问自己**:“单例模式存在的意义是什么?我们为什么要用单例模式?”**

众所周知,在古代封建社会,一个国家都只有一个国王或者叫皇帝。我们在这个国家的任何一个地方,只要提起国王,大家都知道他是谁。因为国王是唯一的。其实这个就是单例模式的核心思想:保证对象的唯一性。

单例模式(Singleton Pattern):确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。 单例模式是一种对象创建型模式。

从其定义我们可以看出来单例模式存在三个要点:

1、实例唯一性
2、自行创建
3、全局访问

如何设计一个优秀的单例模式其实也是围绕着这三点来的。

说了这么多了,还不知道单例模式到底啥样呢?接下来我们一起来着手设计这个“国王”的单例类。我们先看一下单例模式的类图:

单例模式的类图看起来很简单,一个私有的当前类型的成员变量,一个私有的构造方法,一个 getInstance 方法,**创建对象不再通过new 而通过 getInstance 让该类自行创建。**相信我们大多数人使用的单例模式都是这种,因为太简单了。但是单例模式的写法可不止这一种。接下来我们一起来看一下单例模式的九种写法。

单例模式的九种写法

一、饿汉式(静态常量)

/**

  • 饿汉式(静态常量)
    */
    class King {
    private static final King kingInstance = new King();

static King getInstance() {
return kingInstance;
}

private King() {
}
}

  • 优点:这种写法比较简单,就是在类装载的时候就完成实例化。避免了线程同步问题。

  • 缺点:在类装载的时候就完成实例化,没有达到Lazy Loading的效果。如果从始至终从未使用过这个实例,则会造成内存的浪费。

二、饿汉式(静态代码块)

/**

  • 饿汉式(静态代码块)
    */
    class King {
    private static King kingInstance;

static {
kingInstance = new King();
}

private King() {
}

public static King getKingInstance() {
return kingInstance;
}
}

  • 优点:这种写法比较简单,就是在类装载的时候就完成实例化。避免了线程同步问题。

  • 缺点:在类装载的时候就完成实例化,没有达到Lazy Loading的效果。如果从始至终从未使用过这个实例,则会造成内存的浪费。

三、懒汉式(线程不安全)

/**

  • 懒汉式(线程不安全)
    */
    public class King {
    private static King kingInstance;

private King() {
}

public static King getKingInstance() {
if (kingInstance == null) {
kingInstance = new King();
}
return kingInstance;
}
}

优点:懒加载,只有使用的时候才会加载。

缺点:但是只能在单线程下使用。如果在多线程下,一个线程进入了if (singleton == null)判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。所以在多线程环境下不可使用这种方式。

四、懒汉式(线程安全)

/**

  • 懒汉式(线程安全,同步方法)
    */
    public class King {
    private static King kingInstance;

private King() {
}

public static synchronized King getKingInstance() {
if (kingInstance == null) {
kingInstance = new King();
}
return kingInstance;
}
}

  • 优点:懒加载,只有使用的时候才会加载,获取单例方法加了同步锁,保障线程安全。

  • 缺点:效率太低了,每个线程在想获得类的实例时候,执行getInstance()方法都要进行同步。

五、懒汉式(线程安全,同步代码块)

/**

  • 懒汉式(线程安全,同步代码块)
    */
    public class King {
    private static King kingInstance;

private King() {
}

public static King getKingInstance() {
if (kingInstance == null) {
synchronized (King.class) {
kingInstance = new King();
}
}
return kingInstance;
}
}

  • 优点:改进了第四种效率低的问题。

  • 缺点:不能完全保证单例,假如一个线程进入了if (singleton == null)判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。

六、双重检查(DCL)

/**

  • 双重检查(DCL)
    */
    public class King {

private static volatile King kingInstance;

private King() {
}

public static King getKingInstance() {
if (kingInstance == null) {
synchronized (King.class) {
if (kingInstance == null){
kingInstance = new King();
}
}
}
return kingInstance;
}
}

  • 优点:线程安全;延迟加载;效率较高。

  • 缺点:JDK < 1.5 的时候不可用

  • 不可用原因:由于volatile关键字会屏蔽Java虚拟机所做的一些代码优化,可能会导致系统运行效率降低,而JDK 1.5 以及之后的版本都修复了这个问题。(面试装逼用,谨记!!!)

七、静态内部类

/**

  • 静态内部类
    */
    public class King {

private King() {
}

private static class KingInstance{
private static final King KINGINSTANCE = new King();
}

public static King getInstance(){
return KingInstance.KINGINSTANCE;
}
}

  • 优点:避免了线程不安全,延迟加载,效率高。

  • 缺点:暂无,最推荐使用。

  • 特点:这种方式跟饿汉式方式采用的机制类似,但又有不同。

  • 两者都是采用了类装载的机制来保证初始化实例时只有一个线程。不同的地方在饿汉式方式是只要Singleton类被装载就会实例化,没有Lazy-Loading的作用,而静态内部类方式在Singleton类被装载时并不会立即实例化,而是在需要实例化时,调用getInstance方法,才会装载SingletonInstance类,从而完成Singleton的实例化。 类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。

八、枚举

/**

  • 枚举
    */
    public enum King {
    KINGINSTANCE;
    }

  • 优点:不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。

尾声

你不踏出去一步,永远不知道自己潜力有多大,千万别被这个社会套在我们身上的枷锁给捆住了,30岁我不怕,35岁我一样不怕,去做自己想做的事,为自己拼一把吧!不试试怎么知道你不行呢?

改变人生,没有什么捷径可言,这条路需要自己亲自去走一走,只有深入思考,不断反思总结,保持学习的热情,一步一步构建自己完整的知识体系,才是最终的制胜之道,也是程序员应该承担的使命。

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

O-1714664532044)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值