美文网首页
Chapter5 单件模式

Chapter5 单件模式

作者: 小麻巧吃西瓜 | 来源:发表于2019-07-23 20:14 被阅读0次

    单件模式的经典实现:

    public class Singleton {
            //利用一个静态变量来记录Singleton类的唯一实例
        private static Singleton uniqueInstance;
            //构造方法声明为私有
        private Singleton() {}
           
            //若uniqueInstance为空,则不存在实例,则利用私有的构造器产生一个实例,
            //并将它复制到uniqueInstance静态变量中;若不为空,则说明已经有了实例,直接返回。
        public static Singleton getInstance() {
            if (uniqueInstance == null) {
                uniqueInstance = new Singleton();
            }
            return uniqueInstance;
        }
     
        // other useful methods here
    
    }
    

    注意,如果我们不需要这个实例,就永远不会产生,这就是“延迟实例化”。

    线程不安全。


    定义:

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

    类图:

    经典单件模式存在问题,它是线程不安全的。当两个或以上调用getInstance()方法的时候可能出现线程不安全的问题。


    处理线程不安全的方法:

    使用synchronized关键字

    getInstance()方法改为:

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

    该方法的不足之处在于:同步会降低性能,我们只需要第一次执行getInstance()方法的时候同步。这个方法使得每次调用这个方法都会同步,比较累赘。

    解决方法:

    • 如果可以接受同步带来的性能影响,则直接忽略它。
    • 使用“急切”创建实例。
    public class Singleton {
        private static Singleton uniqueInstance = new Singleton();
     
        private Singleton() {}
     
        public static Singleton getInstance() {
            return uniqueInstance;
        }
        
        // other useful methods here
    
    }
    
    

    JVM加载这个类时马上创建唯一的单件实例,保证任何线程访问uniqueInstance静态变量之前,一定先创建此实例。前提是程序总是创建并使用单件实例,或者在创建和运行时负担不太繁重。

    • 用“双重检查加锁”,首先检查是否实例已经创建了,如果尚未创建,“才”进行同步,这样一来,只有第一次才会同步。
    public class Singleton {
        private volatile static Singleton uniqueInstance;
     
        private Singleton() {}
     
        public static Singleton getInstance() {
            //检查实例,如果不存在,就进入同步区块
            if (uniqueInstance == null) {
                synchronized (Singleton.class) {
                    //进入区块后,再检查一次。如果仍是null,才创建实例
                    if (uniqueInstance == null) {
                        uniqueInstance = new Singleton();
                    }
                }
            }
            return uniqueInstance;
        }
    }
    

    volatile关键字可以从可见性和有序性两方面保证线程安全。(此方法不适用于Java 5再之前的版本)


    • 单件模式确保程序中一个类最多只有一个实例。
    • 单件模式也提供访问这个实例的全局点。
    • 单件模式需要私有的构造器,一个静态变量和一个静态方法。
    • 确定在性能和资源的限制条件下,小心选择单件模式以解决多线程问题。

    相关文章

      网友评论

          本文标题:Chapter5 单件模式

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