单例模式学习笔记

本文深入探讨了单例模式的三种实现方式:饿汉式、懒汉式及最优单例模式。详细介绍了每种方式的工作原理、优缺点,并提供了具体的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单例模式

1.饿汉式

1.1描述

单例模式的饿汉类型,是无论我们需不需要实例,我们都自主的去创建实例。在类生成的同时就实现实例的创建,主旨思想为“我都要”。

1.2优缺点

优点:线程安全,创建的实例属于类的成员,且无法被修改

缺点:无论创建的实例是否使用均会创建实例来占用内存空间

1.2代码实现

public class User {
    /**
     * 主动在类生成时创建一个私有的静态的不可变的实例对象
     */
    public  static final User user=new User();

    /**
     * 将唯一的构造方法进行私有化,使得从外部无法直接new新的实例
     */
    private User(){}

    /**
     * 创建一个静态的方法获取我们创建的单例对象
     * @return
     */
    public static User getUser(){
        return user;
    }
}

2.懒汉式

2.1描述

懒汉式实在我们需要时才去创建实例,第一次调用获得实例的方法时,会在方法中判断成员实例为空然后创建实例。

2.2优缺点

优点:内存占用小,延迟加载,仅在需要时创建实例

缺点:加锁,使得多线程情况下需要等待,导致效率第下。

2.3代码实现

public class User {
    /**
     * 创建一个空对象最为单例的基础容器
     */
    public  static User user=null;

    /**
     * 将唯一的构造方法进行私有化,使得从外部无法直接new新的实例
     */
    private User(){}

    /**
     * 创建一个静态的方法获取我们创建的单例对象
     * 调用该方法时若成员单例为空则创建实例对象
     * 加锁实现线程安全
     * @return
     */
    public static synchronized User getUser(){
        if(user==null){
            user=new User();
        }
        return user;
    }
}

2.4效率优化

通过锁代码块与双重检查来将锁的范围减小,只有在第一次多线程并发访问获取实例方法时需要进行锁等待

再用volatile关键字修饰成员实例变量,防止指令重排序

(JMM线程三大特性:原子性,可见性,有序性,volatile针对可见性和有序性有解决方案,懒汉式单例模式主要使用其有序性特点)

代码实现
public class User {
    /**
     * 创建一个空对象最为单例的基础容器
     * 使用volatile防止指令重排序
     */
    public static  volatile User user = null;

    /**
     * 将唯一的构造方法进行私有化,使得从外部无法直接new新的实例
     */
    private User() {
    }

    /**
     * 创建一个静态的方法获取我们创建的单例对象
     * 调用该方法时若成员单例为空则创建实例对象
     * 加锁实现线程安全
     * @return
     */
    public static User getUser() {
        //此判断只为提高效率
        if (user != null) {
            //锁代码块仅对创建实例进行锁机制
            synchronized (User.class) {
                //防止并发访问被锁监听后创建多个实例
                if (user != null) {
                    user = new User();
                }
            }
        }
        return user;
    }
}

3.最优单例模式

3.1描述

通过静态内部类来实现单例,静态内部类不使用则不加载,所以有延迟加载特性;

静态内部类为静态类,其中有一个静态成员方法,使用static修饰符后的类,方法,属性无论多少线程访问均只加载一次

3.2代码实现

public class Item {
    private Item(){}

    public static Item getItem(){
        return InnerItem.item;
    }

    /**
     * 使用静态内部类实现单例
     */
    static class InnerItem{
        private static Item item=new Item();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值