单例模式

一、设计模式概述和分类

1.创建型模式

单例模式、抽象工厂模式、原型模式、建造者模式、工厂模式

2.结构型模式

适配者模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式

3.行为型模式

模板方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式

单例模式

就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)。

一、饿汉式(静态常量)

  1. 构造器私有化(防止new)
  2. 类的内部创建对象
  3. 向外暴露一个静态的公共方法getInstance()
public class Singleton1 {
    //1.构造器私有化
    private Singleton1(){
    }
    //2.内部创建对象实例
    private final static Singleton1 instance = new Singleton1();
    //3.提供一个公有的静态方法,返回实例对象
    public static Singleton1 getInstance(){
        return instance;
    }
}

问题:类装载即完成实例化,可能造成内存浪费。

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

实例的创建放在静态代码块中

public class Singleton2 {
    private Singleton2(){
    }
    private static Singleton2 instance;
    //静态代码块中创建单例对象
    static {
        instance = new Singleton2();
    }
    public static Singleton2 getInstance(){
        return instance;
    }
}

和上述方式相同

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

不可用

public class Singleton3 {
    private static Singleton3 instance;
    private Singleton3(){
    }
    //当使用该方法时,才会创建instance
    public static Singleton3 getInstance(){
        if(instance==null){
            instance = new Singleton3();
        }
        return instance;
    }
}

使用到getInstance()方法时,才会生成实例对象。

但是,这是线程不安全的。一旦多个线程同时到达if(instance==null),并判断为空,那么多个线程都会执行new Singleton3(),会创建多个实例。

四、懒汉式(线程安全)

public class Singleton3 {
    private static Singleton3 instance;
    private Singleton3(){
    }
    //当使用该方法时,才会创建instance
    public static synchronized Singleton3 getInstance(){
        if(instance==null){
            instance = new Singleton3();
        }
        return instance;
    }
}

在方法上添加synchronized关键字,就可以解决线程安全问题,但是效率很低。因为整个方法都是同步的,所有的线程必须串行执行。

五、懒汉式(同步代码块)

不可用

public class Singleton3 {
    private static Singleton3 instance;

    private Singleton3() {
    }

    //当使用该方法时,才会创建instance
    public static Singleton3 getInstance() {
        if (instance == null) {
            synchronized (Singleton3.class) {
                instance = new Singleton3();
            }
        }
        return instance;
    }
}

将同步的机制放在if (instance == null)代码块中,但是只要进入了if代码块,还是会出现线程安全问题,可以说和不加没什么区别

六、双重检查

使用volatile修饰实例,让instance对所有线程是可见的。

同时,在上一个方法的基础上,进入到synchronized代码块中之后,再次进行判断if (instance == null)

外面的if保证效率,里面的if保证安全。

public class Singleton3 {
    private static volatile Singleton3 instance;

    private Singleton3() {
    }

    //当使用该方法时,才会创建instance
    public static Singleton3 getInstance() {
        if (instance == null) {
            synchronized (Singleton3.class) {
                if (instance == null) {
                    instance = new Singleton3();
                }
            }
        }
        return instance;
    }
}

既保证了线程安全,又保证了懒加载。

七、静态内部类

静态内部类的特点:

  1. 当外部类被装载时,静态内部类不会被装载。
  2. 只会被装载一次
public class Singleton5 {
    private Singleton5() {
    }
    private static class SingletonInstance{
        private static final Singleton5 INSTANCE = new Singleton5();
    }
    public static Singleton5 getInstance(){
        return SingletonInstance.INSTANCE;
    }
}
  • 这种方式采用了类装载的机制来保证初始化实例时只有一个线程
  • 静态内部类方式在Singleton类被装载的时候并不会立即实例化,而是在需要实例化的时候,调用getInstance()方法,才会装载SingletonInstance类,从而完成Singleton的实例化。
  • 类的静态属性只会在第一次加载类的时候初始化,所以JVM帮我们保证了线程的安全性。

八、枚举

public enum  Singleton4 {
    instance;
}

使用枚举来实现,不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象

单例模式在JDK源码中的使用

java.lang.Runtime就是最经典的单例模式,用的是饿汉式。
在这里插入图片描述

小结

  • 单例模式保证了系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能。
  • 当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用new;
  • 使用场景:需要频繁的进行创建和销毁的对象、创建对象耗时过多耗费资源过多,但又经常使用到的对象、工具类对象、频繁访问数据库或文件的对象(比如数据源、session工厂等)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值