美文网首页
实现 Singleton 模式

实现 Singleton 模式

作者: Rarestzhou | 来源:发表于2018-09-08 09:35 被阅读0次

题目:设计一个类,只能生成该类的一个实例

单例模式的组成:

使用一个私有构造函数、一个私有静态变量以及一个公有静态函数来实现。

私有构造函数保证了不能通过构造函数来创建对象实例,只能通过公有静态函数返回唯一的私有静态变量

代码展示:

/**
 * 单例模式
 */
public class SingletonDemo {

    /**
     * 单例模式,懒汉式,线程不安全
     */
    public static class Singleton {
        private static Singleton uniqueInstance;

        private Singleton() {

        }

        public static Singleton getInstance() {
            if (uniqueInstance == null) {
                uniqueInstance = new Singleton();
            }
            return uniqueInstance;
        }
    }

    /**
     * 单例模式,饿汉式,线程安全
     */
    public static class Singleton2 {
        private static Singleton2 instance  = new Singleton2();

        private Singleton2() {

        }

        public static Singleton2 getInstance() {
            if (instance == null) {
                instance = new Singleton2();
            }

            return instance;
        }
    }


    /**
     * 单例模式,饿汉式,线程安全,多线程环境下效率不高
     */
    public static class Singleton3 {
        private static Singleton3 instance = null;

        private Singleton3() {

        }

        public static synchronized Singleton3 getInstance() {
            if (instance == null) {
                instance = new Singleton3();
            }

            return instance;
        }
    }

    /**
     * 单例模式,饿汉式,变种,线程安全
     */
    public static class Singleton4 {
        private static Singleton4 instance;

        static {
            instance = new Singleton4();
        }

        private Singleton4() {

        }

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

    /**
     * 单例模式,懒汉式,使用静态内部类,线程安全【推荐】
     */
    public static class Singleton5 {

        private static class SingletonHolder {
            private static final Singleton5 INSTANCE = new Singleton5();
        }

        private Singleton5() {

        }

        public static Singleton5 getInstance() {
            return SingletonHolder.INSTANCE;
        }
    }

    /**
     * 使用枚举方式,线程安全【推荐】
     *
     * 枚举自己处理序列化
     */
    public enum Singleton6 {
        INSTANCE
    }

    /**
     * 使用双重校验锁,线程安全【推荐】
     */
    public static class Singleton7 {
        private volatile static Singleton7 instance = null;

        private Singleton7() {

        }

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

            return instance;
        }
    }

    public static void main(String[] args) {
        System.out.println(Singleton.getInstance() == Singleton.getInstance());
        System.out.println(Singleton2.getInstance() == Singleton2.getInstance());
        System.out.println(Singleton3.getInstance() == Singleton3.getInstance());
        System.out.println(Singleton4.getInstance() == Singleton4.getInstance());
        System.out.println(Singleton5.getInstance() == Singleton5.getInstance());
        System.out.println(Singleton6.INSTANCE == Singleton6.INSTANCE);
        System.out.println(Singleton7.getInstance() == Singleton7.getInstance());

        // 输出结果:全为 true
    }
}


volatile 关键字的含义:

  • 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,新值对其他线程是立即可见的
  • 禁止进行指令重排序

volatile 的不足:无法保证原子性

volatile 的使用条件:

  • 对变量的写操作不依赖于当前值
  • 该变量没有包含在具有其他变量的不变式中 (a <= b)

为什么使用枚举实现单例模式是最好的方法?

  1. 写法简单
 public enum Singleton6 {
        INSTANCE
    }
  1. 枚举自己处理序列化

    我们知道,以前的所有的单例模式都有一个比较大的问题,就是一旦实现了Serializable接口之后,就不再是单例得了,因为,每次调用 readObject()方法返回的都是一个新创建出来的对象,有一种解决办法就是使用readResolve()方法来避免此事发生。但是,为了保证枚举类型像Java规范中所说的那样,每一个枚举类型极其定义的枚举变量在JVM中都是唯一的,在枚举类型的序列化和反序列化上,Java做了特殊的规定。大概意思就是说,在序列化的时候Java仅仅是将枚举对象的name属性输出到结果中,反序列化的时候则是通过java.lang.Enum的valueOf方法来根据名字查找枚举对象。同时,编译器是不允许任何对这种序列化机制的定制的,因此禁用了writeObject、readObject、readObjectNoData、writeReplace和readResolve等方法。

  1. 枚举实例创建是线程安全的

    当一个Java类第一次被真正使用到的时候静态资源被初始化、Java类的加载和初始化过程都是线程安全的。所以,创建一个enum类型是线程安全的。

相关文章

  • 实现Singleton模式

    面试题 2实现Singleton模式

  • 实现 Singleton 模式

    题目:设计一个类,只能生成该类的一个实例 单例模式的组成: 使用一个私有构造函数、一个私有静态变量以及一个公有静态...

  • 实现Singleton模式

    题目:设计一个类,我们只能生成该类的一个实例题目其实说到底只是常见的单例模式,相信大家对这个最基础的设计模式早已有...

  • 实现Singleton模式

    什么是Singleton模式? 如何实现Singleton模式 解法一(只适用于单线程)由于只能生成一个实例,因此...

  • 实现 singleton 模式

    https://stackoverflow.com/questions/1008019/c-singleton-d...

  • 实现Singleton模式

    不好的解法-:只适用于单线程环境 设想如果两个线程同时运行到判断instance是否为null的if语句,并且in...

  • Python单例模式(Singleton)的N种实现

    Python单例模式(Singleton)的N种实现

  • go设计模式代码实现

    go 设计模式代码实现 单例模式 代码实现 type singleton struct{} var ins *si...

  • 单例模式

    Singleton模式 只有一个实例 1. Singleton模式 Singleton模式的目的: 想确保任何情况...

  • 单例模式

    单例模式及C++实现代码单例模式4种实现详解 c++11改进我们的模式之改进单例模式 单例模式(Singleton...

网友评论

      本文标题:实现 Singleton 模式

      本文链接:https://www.haomeiwen.com/subject/gzdkgftx.html