单例设计模式

单例

零、单例设计模式

单例设计模式:采取一定的方法保证整个软件系统中,对某个类只能存在一个对象实例;并且该类只提供一个取得其对象实例的静态方法。

1、构造器私有化(防止new)

2、向外暴露一个静态的公共方法

一、饿汉式:成员变量初始化

1、代码
/**
 * @Author: dashu
 * @Description: 单例(饿汉式:成员变量初始化)
 * @Version: 1.0
 */
public class Singleton {

    private final  static  Singleton singleton = new Singleton();

    private Singleton(){}

    public static Singleton getInstance(){
        return singleton;
    }

}
2、小结

优点:写法简单,在类装载时就完成实例化。避免了线程同步问题,线程安全的。

缺点:没有达到懒加载的效果,如果从始至终从未使用该实例,则造成内存的浪费

结论:该单例模式可以用,但可能造成内存浪费

二、饿汉式:静态代码块初始化

1、代码
/**
 * @Author: dashu
 * @Description: 单例(饿汉式:静态代码块初始化)
 * @Version: 1.0
 */
public class Singleton {
    
    private final  static  Singleton singleton;

    static {
        singleton = new Singleton();
    }
    
    private Singleton(){}
    
    public static Singleton getInstance(){
        return singleton;
    }
    
}
2、小结

优点:写法简单,在类装载时就完成实例化。避免了线程同步问题,线程安全的。

缺点:没有达到懒加载的效果,如果从始至终从未使用该实例,则造成内存的浪费

结论:该单例模式可以用,但可能造成内存浪费

三、懒汉式,线程不安全

1、代码
/**
 * @Author: dashu
 * @Description: 单例(懒汉模式)
 * @Version: 1.0
 */
public class Singleton {

    private static Singleton singleton;

    private Singleton() {
    }

    public static Singleton getInstance() {

        if (singleton == null) {
            singleton = new Singleton();
        }

        return singleton;
    }

}
2、小结

优点:起到了懒加载的效果

缺点:只能在单线程下使用。如果在多线程下,一个线程进入了if (singleton == null)语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时会产生多个实例,违反单例模式。

结论:不要使用这种方式

四、懒汉模式:同步方法,线程安全

1、代码
/**
 * @Author: dashu
 * @Description: 单例(懒汉模式:同步方法)
 * @Version: 1.0
 */
public class Singleton {

    private static Singleton singleton;

    private Singleton(){}
    
    public static synchronized Singleton getInstance(){
        if (singleton == null){
            singleton = new Singleton();
        }
        return singleton;
    }
    
}
2、小结

优点:起到了懒加载的效果,同时解决了线程安全问题

缺点:效率低下,在多线程下,每个线程在获取该类的实例时,执行到getInstance()方法都要进行同步。而其实这个方法只执行一次实例化代码就够了,后面的想获得该类实例,直接return就行了。

结论:不推荐使用

五、懒汉模式:同步代码块,线程不安全

1、代码
/**
 * @Author: dashu
 * @Description: 单例(懒汉模式:同步代码块)
 * @Version: 1.0
 */
public class Singleton {


    private  static Singleton singleton;

    private Singleton() {
    }

    public static Singleton getInstance() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                singleton = new Singleton();
            }
        }
        return singleton;
    }

}
2、小结

优点:起到了懒加载的效果

缺点:线程不安全的,在多线程下,一个线程进入了if (singleton == null)语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时会产生多个实例,违反单例模式。

结论:不要使用这种方式

六、懒汉模式:同步代码块,双重验证

1、代码
/**
 * @Author: dashu
 * @Description: 单例(懒汉模式:同步代码块,双重验证)
 * @Version: 1.0
 */
public class Singleton {
    
    private  static  Singleton singleton;
    
    private Singleton(){}
    
    public static Singleton getInstance(){
        if (singleton == null){
            synchronized (Singleton.class){
                if (singleton == null){
                    singleton =new Singleton();
                }
            }
        }
        return singleton;
    }
    
}
2、小结

优点:线程安全,懒加载,效率高

结论:推荐使用

七、静态内部类

1、代码
public class Singleton {

    public static class SingletonInstance {
        private final static Singleton INSTANCE = new Singleton();
    }

    private Singleton() {
    }

    public static Singleton getInstance() {
        return SingletonInstance.INSTANCE;
    }

}
2、小结

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

静态内部类方式在Singleton类被装载时并不会立即实例化,而是在需要实例化时,调用getInstance()方法,才会装载SingletonInstance类,从而完成Sinleton的实例化。

类的静态属性只会在第一次加载类的时候初始化,这里JVM帮助我们保证了线程的安全性,在类初始化时,别的线程是无法进入的

优点:线程安全,懒加载,效率高

结论:推荐使用

八、枚举

1、代码
/**
 * @Author: dashu
 * @Description: 单例(枚举)
 * @Version: 1.0
 */
public enum Singleton {
    INSTANCE;

}
2、小结

借助JDK1.5中添加的枚举来实现单例模式。不仅能避免多线程同步问题,而且还能放hi反序列化重新创建新的对象

这种方式是Effective Java作者Josh Bloch提倡的方式

结论:推荐使用

九、测试

1、前七种
/**
 * @Author: dashu
 * @Description: 测试
 * @Version: 1.0
 */
public class Main {

    public static void main(String[] args) {
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();
        System.out.println("singleton1 == singleton2 :" + (singleton1 == singleton2));
        System.out.println("singleton1.hashCode() :" + singleton1.hashCode());
        System.out.println("singleton2.hashCode() :" + singleton2.hashCode());
    }

}

在这里插入图片描述

2、枚举
/**
 * @Author: dashu
 * @Description: 测试
 * @Version: 1.0
 */
public class Main {

    public static void main(String[] args) {
        Singleton singleton1 = Singleton.INSTANCE;
        Singleton singleton2 = Singleton.INSTANCE;
        System.out.println("singleton1 == singleton2 :" + (singleton1 == singleton2));
        System.out.println("singleton1.hashCode() :" + singleton1.hashCode());
        System.out.println("singleton2.hashCode() :" + singleton2.hashCode());
    }

}

在这里插入图片描述

十、单例模式注意事项和细节说明

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

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

单例模式的使用场景:

1、需要频繁创建销毁的对象

2、创建对象时耗时过多或耗费资源过多(即:重量级对象)

3、经常用到的对象

4、工具类对象

5、频繁访问数据库或文件的对象(如:数据源、session工厂等)

十一、总结

类型是否支持懒加载线程是否安全效率推荐指数
饿汉式:成员变量初始化5
饿汉式:静态代码块初始化5
懒汉式0
懒汉模式:同步方法5
懒汉模式:同步代码块0
懒汉模式:同步代码块,双重验证10
静态内部类10
枚举10
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大树下躲雨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值