【设计模式笔记】单例模式

本文详细介绍了Java中的单例模式,包括饿汉模式、懒汉模式和双重检查模式,以及它们在多线程环境下的安全性。同时,也探讨了Kotlin中利用object关键字和懒加载单例的实现方式,强调了单例模式在节省内存和保证线程安全方面的优化策略。
摘要由CSDN通过智能技术生成

特点

A private constructor [私有构造函数]
A static reference of its class[当前类的静态引用]
One static method [一个静态方法获取实例]
Globally accessible object reference [允许全局获取]
Consistency across multiple threads [跨线程安全]

存在类型:

1、饿汉模式

直接赋值,用static标志,类加载较慢;

// 饿汉模式:直接进行加载,在类加载时直接进行赋值;
public class Singleton {
    // 1. 属性私有化; 2.static关键字获取,类加载时会直接加载;
    private static Singleton singleton = new Singleton();

    private Singleton() {
    }

    public static Singleton getInstance() {
        return singleton;
    }
}

2、懒汉模式:

使用时再加载

public class Singleton {
    private static Singleton singleton;

    private Singleton() {
    }

    public static Singleton getInstance() {
        // 数据在获取时新建,需要加锁避免线程不安全
        synchronized(getInstance()) {
            if (singleton == null) singleton = new Singleton();
            return singleton;
        }
    }
}

3、双重检查模式

单例模式的创建&优化过程:
(1)需要在使用这个对象的时候才创建,节省内存;
解决:在调用"提供对象的方法"的时候才创建

(2)可能多线程不安全;
解决:对整个"提供对象的方法"的时候加锁;

(3)锁住整个方法消耗太大了;
解决:双重锁检测机制;

public class Singleton {
    // 设置可见性
    private volatile static Singleton singleton;

    private Singleton() { }

    public static Singleton getInstance() {
        // 避免锁住当前方法,只在singleton为null需要创建时才枷锁
        if (singleton == null) {
            synchronized(Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();

                }
            }
        }
        return singleton;
    }
}

两次判空解决了什么问题:
第一个判断为空 --> 解决的效率问题,不需要每个线程都拿住锁;
第二个判断为空 --> 防止线程不安全

kotlin使用单例的两种用法:

参考文章: https://blog.mindorks.com/how-to-create-a-singleton-class-in-kotlin

(1)直接使用object;

  • kotlin中object是全局静态类,即用object标记的方法全局只存在一个且在放在栈中;
  • kotlin中object是可以继承一个class的;

(2)懒加载单例

In early initialization, all the components are initialized in the
Application.onCreate() using the init() functions. But this results in
slowing down the application startup by blocking the main thread. So,
it is generally advised to use the lazy initialization
way.【在初始化时,所有的组件都会在Applicat.onCreate()中实现。但这会阻塞主线程和延迟app启动时间。因此,可以通过懒加载方式实现单例】

open class SingletonHandler<out T: Any>(creator: () -> T) {
    private var creator: (() -> T)? = creator

    @Volatile
    private var instance: T? = null

    // 双重检测懒汉式
    fun getInstance(): T {
        // 直接返回instance,由于instance可为空,会报错;
        val resInstance = instance
        if (resInstance != null) return resInstance
        return synchronized(this) {
            val res = instance
            if (res != null) {
                res
            } else {
                val created = creator!!()
                instance = created
                creator = null
                created
            }
        }
    }
}

class MySingleton private constructor() {
    // 初始化时懒加载, 使用
    companion object: SingletonHandler<MySingleton>(::MySingleton) {
    }
}

获取方式:

class Test() {
    fun test() {
        val mySingleton = MySingleton.getInstance()
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值