美文网首页
设计模式学习-单例模式

设计模式学习-单例模式

作者: most_xiaoya | 来源:发表于2018-11-10 14:44 被阅读0次

    单例模式: 确保一个类只有一个实例,并提供一个全局访问点。

    单例模式要素:
    a)私有构造方法
    b)私有静态引用指向自己实例
    c)以自己实例为返回值的公有静态方法

    一般要实现一个单例 最简单的方式:

    public class SingleInstance {
        private static SingleInstance instance;
        private SingleInstance() {
        }
        public static SingleInstance getInstance() {
            if (null == instance)
                instance = new SingleInstance();
            return instance;
        }
    }
    

    但是这样会有一个问题,当多个线程同时调用 getInstance() 方法时,可能会产生多个instance 实例,因此这种方式并不是真正的单例。
    为了解决线程安全问题,我们只需要在getInstance() 方法上使用synchronized 关键字给线程加锁即可。

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

    synchronized 的作用是加锁,当多个线程同时调用getInstance() 时,只有一个线程能进入,其他线程会等待进入的线程出来之后在一一进入,这样就能保证instance 实例是唯一的。这才是真正的单例。
    不过这并不是完美的解决方案,只要是锁,必然有性能损耗问题。而且对于上面的代码,其实我们只需要在线程第一次访问时加锁即可,之后并不需要锁,锁给我们带来了系统资源浪费。

    上面两种方式都是在getInstance() 方法中创建实例,也就是说在要调用的时候才创建实例,这种方式被称为“懒汉式”,英文名,叫 lazy loading,也就是延迟加载。
    新的解决方案是not lazy loading,在类加载时就创建好了实例:

    public class SingleInstance {
    
        private static SingleInstance instance = new SingleInstance();
    
        private SingleInstance() {
        }
    
        public static SingleInstance getInstance() {
            return instance;
        }
    }
    
    

    这种方式就可以保证实例唯一。

    除了上面的几种方式,还有一种叫 double-checked locking (双重检查加锁)
    这种方式主要用到两个关键字volatile 和 synchronized,代码如下:

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

    volatile 关键字简单来说就是可以保证instance变量在被其中一个线程new出来时,其他线程可以立即看到结果并正确的处理它。

    总结:感觉平时一般可以直接用

    public class SingleInstance {
    
        private static SingleInstance instance = new SingleInstance();
    
        private SingleInstance() {
        }
    
        public static SingleInstance getInstance() {
            return instance;
        }
    }
    
    

    就可以满足需求了。ok 单例就说到这儿了,优点儿?
    优点就是使用单例模式,对象在内存中只有一个实例,并且无需频繁的创建和销毁对象,大大的减少了性能的损耗。

    相关文章

      网友评论

          本文标题:设计模式学习-单例模式

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