欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java设计模式之单例模式

程序员文章站 2022-05-04 17:25:08
...

如果说设计模式也有知名度排名,个人觉得单例模式应该排到第一名。单例模式说简单也简单,说难也难,主要在于不同情况之下应该有不同的选择。

单例特点
  • 单例类只能有一个实例。
  • 单例类必须自己创建自己的唯一实例。
  • 单例类必须给所有其他对象提供这一实例。
饿汉模式(线程安全)
public class SingletonDemo {
    private static final SingletonDemo singleton = new SingletonDemo();
    private SingletonDemo() {
        super();
    }
    public static SingletonDemo getSingleton() {
        return singleton;
    }

构造函数私有化,这个是常规操作。如果构造函数不私有化,那就可以随时随地 new 一个对象,违背了单例的初衷。

懒汉模式(线程不安全)
public class SingletonDemo {
    private static SingletonDemo singleton;
    private SingletonDemo() {
        super();
    }
    public static SingletonDemo getSingleton() {
        if (singleton == null) {
            singleton = new SingletonDemo();
        }
        return singleton;
    }
}

这是教科书上面标准的懒汉模式代码,按需加载。这段代码单线程没有任何问题,多线程就会出现问题,如图所示,会产生两个实例。
Java设计模式之单例模式

懒汉模式(线程安全)
    public synchronized static SingletonDemo getSingleton() {
        if (singleton == null) {
            singleton = new SingletonDemo();
        }
        return singleton;
    }

直接对这个方法加锁,简单粗暴的同步方式,但后续的访问每次都需要竞争锁,开销比较大,这是不必要的开销,就有了新的加锁方式—双重锁。

双重锁模式(线程安全)
    public static SingletonDemo getSingleton() {
        if (singleton == null) {
            synchronized (SingletonDemo.class) {
                if (singleton == null) {
                    singleton = new SingletonDemo();
                }
            }
        }
        return singleton;
    }

这种方式有效的避免了后续竞争锁的开销,只有第一次初始化的时候竞争锁,对上一段代码优化。

静态内部类(线程安全)
    public static SingletonDemo getSingleton() {
        return SingletonHolder.instance;
    }

    private static class SingletonHolder {
        private static final SingletonDemo instance = new SingletonDemo();
    }

这是利用内部类加载特点实现的线程安全性。

枚举单例(线程安全)
    public enum Singleton {
        SINGLETON;

        public void toDo() {
            //TODO
        }
    }

这是很多大牛都推荐的一种单例实现方式,这个模式单例可以完美避免所有问题,记住是所有问题,不仅仅是线程安全问题。利用了枚举的特性,完美实现了单例。

总结

只追求技术的程序员不是好程序员的,正所谓没有最优的选择,只有最合适的选择,没有场景需要的技术选型,都是耍流氓的。

单例模式这么多,除了枚举,其余都存在一些除了线程安全之外的问题,结合上一篇讲的「Java对象的创建方式」猜测一下会存在哪些问题?


欢迎大家关注我的微信公众号:卡戎
Java设计模式之单例模式

相关标签: java 设计模式