设计模式-单例

发布时间 2024-01-01 22:00:24作者: 轻寒

单例模式

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

缺点:当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法(getInstance()等),而不是使用new,可能会给其他开发人员造成困扰,特别是看不到源码的时候。

使用场景:

  • 需要频繁的进行创建和销毁的对象;
  • 创建对象时耗时过多或耗费资源过多,但又经常用到的对象
  • 工具类对象;
  • 频繁访问数据库或文件的对象。

饿汉

public class Singleton3 {
    //饿汉模式,它基于 classloader 机制避免了多线程的同步问题
    private static Singleton3 instance = new Singleton3();

    private Singleton3() {
    }

    public static Singleton3 getInstance() {
        return instance;
    }
}

懒汉

public class Singleton5 {
    /**
     * 对singleton使用volatile约束,保证他的初始化过程不会被指令重排。
     * 除了引入了时间片以外,由于处理器优化和指令重排等,CPU还可能对输入代码进行乱序执行,比如load->add->save 有可能被优化成load->save->add 。这就是可能存在有序性问题。
     * 在以下两个场景中可以使用volatile来代替synchronized:
     * 1、运算结果并不依赖变量的当前值,或者能够确保只有单一的线程会修改变量的值。
     * 2、变量不需要与其他状态变量共同参与不变约束。
     * 除以上场景外,都需要使用其他方式来保证原子性,如synchronized或者concurrent包。
     */
    private volatile static Singleton5 instance = null;

    private Singleton5() {
    }

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

静态变量

public class Singleton6 {
    private Singleton6(){}

    private static class SingleonInstance{
        /**
         * 静态内部类[推荐使用]
         * 这种方式跟饿汉式方式采用的机制类似,但又有不同。两者都是采用了类装载的机制来保证初始化实例时只有一个线程。
         * 不同的地方在饿汉式方式是只要Singleton类被装载就会实例化,没有Lazy-Loading的作用,
         * 而静态内部类方式在Singleton类被装载时并不会立即实例化,而是在需要实例化时,调用getlinstance方法,
         * 才会装载Singletonlnstance类,从而完成Singleton的实例化。类的静态属性只会在第一次加载类的时候初始化,
         * 所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。
         * 优点: 避免了线程不安全,延迟加载,效率高
         */
        private static final Singleton6 INSTANCE=new Singleton6();
    }

    public static Singleton6 getInstance(){
        return SingleonInstance.INSTANCE;
    }
}