美文网首页
单例模式

单例模式

作者: 阿彪Biao | 来源:发表于2019-01-03 23:19 被阅读0次

    结构

    image.png

    1.为什么要使用单例模式?

    • 空间角度:节省内存,因为内存中只有一个对象
    • 时间角度:可以避免重复的创建对象和销毁对象,提高程序的性能

    2.实现方式

    1.饿汉模式

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

    优点:线程安全
    因为在类装载的时候就完成了实例化,可以避免线程同步的问题。JVM在类进行初始化的阶段会获得一个锁,这个锁可以同步多个线程对同一类进行初始化。而对static变量的初始化属于类初始化的一部分。
    缺点:可能会造成内存浪费
    如果在从来没有使用过这个类,那个这个实例化这个类就没有意义。

    2.懒汉模式

    懒汉模式就是为了解决饿汉模式中的缺点,他的目的就是让我们这使用这个类的时候才去实例化类,避免造成无用的实例化。

    懒汉模式有以几种不同的实现方式

    • 线程不安全版本。这个版本只能在单线程下使用
    public class Singleton {  
        private static Singleton instance;  
        private Singleton (){}  
      
        public static Singleton getInstance() {  
        if (instance == null) {  
            instance = new Singleton();  
        }  
        return instance;  
        }  
    }
    

    • 线程安全版本。效率低

    因为在每次调用getInstance方法的时候都要进行同步操作。即使这个类已经被实例化了。很显然是没有必要的。

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

    双重校验锁——线程安全的优化版本。(推荐使用)

    这个是如何优化上面线程安全的版本的呢?
    第一层的判断是为了避免不必要的同步,第二层判断则是在null的情况下创建实例

    volatile关键词在过程中起到什么作用?

    public class Singleton {  
        private volatile static Singleton singleton;  
        private Singleton (){}  
        public static Singleton getSingleton() {  
        if (singleton == null) {  
            synchronized (Singleton.class) {  
            if (singleton == null) {  
                singleton = new Singleton();  
            }  
            }  
        }  
        return singleton;  
        }  
    }
    

    • 静态内部类实现单例模式,线程安全,并且是懒加载(推荐使用

    饿汉模式中提到JVM的类加载机制保证了在实例化对象时是线程安全。静态内部内就是利用这种思想来实现线程安全的。在对静态内部类static变量实例化的时候是线程安全的。并且这种方式也能实现在使用的时候才去实例化类。

    public class Singleton {  
        private static class SingletonHolder {  
          private static final Singleton INSTANCE = new Singleton();  
        }  
        private Singleton (){}  
        public static final Singleton getInstance() {  
          return SingletonHolder.INSTANCE;  
        }  
    }
    

    相关文章

      网友评论

          本文标题:单例模式

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