单例模式的八种实现方式

本文详细介绍了Java中的单例模式实现,包括饿汉式(静态常量和静态代码块)、懒汉式(线程不安全、线程安全的同步方法和同步代码块)、双重检查和静态内部类以及枚举方式。分析了各种方式的优缺点,如线程安全、延迟加载和内存使用。最后推荐使用静态内部类和枚举方式,因为它们既保证了线程安全又提高了效率。
摘要由CSDN通过智能技术生成

单例模式

饿汉式(静态常量)
/**
 * @Author: Antares
 * @Date: 2020/2/21 22:22
 */
public class Single01 {
    public static void main(String[] args) {
        SingleTon instance01 = SingleTon.getInstance();
        SingleTon instance02 = SingleTon.getInstance();
        System.out.println(instance01 == instance02);
    }
}

class SingleTon{
    /**
     * 构造私有化,外部new
     */
    private SingleTon(){

    }

    /**
     * 本类内部创建对象实例
     */
    private final static SingleTon instance = new SingleTon();

    /**
     *
     * @return instance
     */
    public static SingleTon getInstance() {
        return instance;
    }

}
饿汉式(静态代码块)
/**
 * @Author: Antares
 * @Date: 2020/2/21 22:40
 */
public class SingleTon02 {

    public static void main(String[] args) {
     SingleTon instance01 = SingleTon.getInstance();
     SingleTon instance02 = SingleTon.getInstance();
     System.out.println(instance01 == instance02);
    }
}

class SingleTon{
    /**
     * 构造私有化,外部new
     */
    private SingleTon(){


    }

    /**
     * 本类内部创建对象实例
     */
    private  static SingleTon instance ;

    // 静态代码块中创建单例对象
    static {
        SingleTon instance = new SingleTon();
    }

    /**
     *
     * @return instance
     */
    public static SingleTon getInstance() {
        return instance;
    }

}

优点: 写法简单,在类装载时实例化,避免了线程同步问题

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

结论: 这种单例模式可用,可能造成内存浪费

懒汉式(线程不安全)
/**
 * @Author: Antares
 * @Date: 2020/2/21 22:52
 */
public class SingleTon03 {
    public static void main(String[] args) {
        SingleTon instance01 = SingleTon.getInstance();
        SingleTon instance02 = SingleTon.getInstance();
        System.out.println(instance01 == instance02);
    }
}

class SingleTon{
    private static SingleTon instance;

    private SingleTon() {

    }

    /**
     * 提供一个静态公有方法,当使用到该方法时,才去创建instance
     * 即懒汉式
     */
    public static SingleTon getInstance() {
        if (instance == null) {
            instance = new SingleTon();
        }
        return instance;
    }
}

优点: 起到了Lazy Loading 的效果,但是只能在单线程下使用

缺点: 如果在多线程下.一个线程进入if,还没来得及往下执行,另一个线程也通过了这个判断语句,这时候会出现多个实例

结论: 在实际开发中,不能使用这种方式

懒汉式(线程安全,同步方法)
 public static synchronized SingleTon getInstance() {
        if (instance == null) {
            instance = new SingleTon();
        }
        return instance;
    }

解决了线程不安全问题,但是效率太低

结论: 可用,不推荐

懒汉式(线程安全,同步代码块)
 public static  SingleTon getInstance() {
        if (instance == null) {
            synchronized (SingleTon.class) {
                 instance = new SingleTon();
            }
        }
        return instance;
    }

本意是解决效率低,但是这种同步不能起到线程同步作用

结论: 不能用

双重检查
 /**
     * 提供一个静态公有方法,当使用到该方法时,加入双重检查才去创建instance
     * 即懒汉式
     */
    public static  SingleTon getInstance() {
        if (instance == null) {
            synchronized (SingleTon.class) {
                instance = new SingleTon();
            }
        }
        return instance;
    }

Double Check 概念是多线程开发中经常用到的,线程安全,延迟加载,效率较高

结论: 开发中经常使用

静态内部类
/**
 * @Author: Antares
 * @Date: 2020/2/21 23:13
 */
public class SingleTon07 {

    public static void main(String[] args) {
        SingleTon instance01 = SingleTon.getInstance();
        SingleTon instance02 = SingleTon.getInstance();
        System.out.println(instance01 == instance02);
    }
}

class SingleTon{
    private static volatile SingleTon instance;

    private SingleTon() {

    }

    private static class SingleTonInstance {
        private static final SingleTon INSTANCE = new SingleTon();
    }

    /**
     * 提供一个静态公有方法,当使用到该方法时,加入双重检查才去创建instance
     * 即懒汉式
     */
    public static  SingleTon getInstance() {

        return SingleTonInstance.INSTANCE;
    }
}

这种方式采用了类加载的机制来保证初始化实例时只有一个线程

类的静态属性只会在第一次加载时初始化,保证了线程的安全性

结论: 推荐使用

枚举
/**
 * @Author: Antares
 * @Date: 2020/2/21 23:14
 */
public class SingleTon08 {
    public static void main(String[] args) {
        Singleton instance = Singleton.INSTANCE;
        Singleton instance01 = Singleton.INSTANCE;
        System.out.println(instance == instance01);

    }
}

enum Singleton {
    INSTANCE;
    public void sayOK() {
        System.out.println("ok");
    }
}

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

结论: 推荐使用

单例模式保证了系统内存中该类只存在一个对象,节省资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能

当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用new

单例模式使用的场景:需要频繁的进行创建和销毁的对象,创建对象时好事时多时少或耗费资源过多(重量级的对象,但又经常用到的额对象,工具类对象,频繁访问数据库或文件的对象

javalang.RunTime就是经典的单例模式

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值