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

设计模式-单例模式

作者: ZjyMac | 来源:发表于2018-03-26 17:55 被阅读0次

    一,单例概念

    单例模式是一种对象创建模式,它用于产生对象的具体实例,并且确保在系统中这个类只能产生一个实例。

    • 好处
      (1)对于频繁使用的对象,可以省略创建对象花费的时间,对于一些重量级的对象,是一笔可观的系统开销
      (2)由于new的操作减少,对系统内存的使用频率也会减少,减少GC压力,压缩GC停顿时间。

    二,单例的写法

    • 饿汉模式
    public class EagerSingleton {
    
        private static EagerSingleton eagerSingleton = new EagerSingleton();
    
        private EagerSingleton() {
        }
    
        public static EagerSingleton getEagerSingleton() {
            return eagerSingleton;
        }
    }
    
    

    优点:类装载的时候就完成类实例化,避免了线程同步问题
    缺点:没实现延迟加载,如果不使用这个类会造成内存浪费

    • 懒汉模式(对于饿汉模式的没有懒加载的方式的一种优化)- 不建议使用
    public class LazyModeSingleton {
       private static LazyModeSingleton lazyModeSingleton;
    
       private LazyModeSingleton() {
       }
    
       public static LazyModeSingleton getInstance() {
           if (lazyModeSingleton == null) {
               lazyModeSingleton = new LazyModeSingleton();
           }
           return lazyModeSingleton;
       }
    }
    

    缺点:线程非安全

    • 懒汉线程安全
    public class LazyModeSingletonSafe {
        private static LazyModeSingletonSafe lazyModeSingletonSafe;
    
        private LazyModeSingletonSafe() {
        }
    
        public static synchronized LazyModeSingletonSafe getInstance() {
            if (lazyModeSingletonSafe == null) {
                lazyModeSingletonSafe = new LazyModeSingletonSafe();
            }
            return lazyModeSingletonSafe;
        }
    
    //    public static LazyModeSingletonSafe getInstance() {
    //        synchronized (LazyModeSingleton.class) {
    //            if (lazyModeSingletonSafe == null) {
    //                lazyModeSingletonSafe = new LazyModeSingletonSafe();
    //            }
    //        }
    //        return lazyModeSingletonSafe;
    //    }
    }
    

    优点:线程安全
    缺点:性能差

    • DCL(双重检查锁机制)
    public class DCLSingleton {
        private static volatile DCLSingleton dclSingleton;//禁止指令jvm重排序
    
        private DCLSingleton() {
    
        }
    
        private DCLSingleton getInstance() {
            if (dclSingleton == null) {
                synchronized (DCLSingleton.class) {
                    if (dclSingleton == null) {
                        //JVM的及时编译器中存在指令重排序优化会导致线程不安全,解决办法 关键字valatile
                        dclSingleton = new DCLSingleton();}
                }
            }
            return dclSingleton;
        }
    }
    
    • 静态内部类(建议使用)
    public class StaticInneClassesSingleton {
        private StaticInneClassesSingleton() {
        }
    
        public static StaticInneClassesSingleton getInstance() {
            return StaticInneClassesSingletonHolder.staticInneClassesSingleton;
        }
    
        private static class StaticInneClassesSingletonHolder {
            private final static StaticInneClassesSingleton staticInneClassesSingleton = new StaticInneClassesSingleton();
        }
    }
    

    优点:具有延迟加载,线程安全,性能优越
    原因:使用了static final关键字

    • 枚举
    public class EnumSingleton {
        INSTANCE;
        public void  doSomeTing(){
    
        }
    }
    
    

    借助JDK1.5中添加的枚举来实现单例模式。不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。

    总结:

    饿汉模式:无法实现延迟加载
    懒汉模式:非线程安全
    懒汉模式(线程安全):使用synchronized导致性能缺陷
    DCL:JVM及时编译器指令的重排序问题,通过关键字volatile 可以解决,但是也具有一定性能问题
    静态内部类/枚举:延迟加载,线程安全,性能好建议使用

    三,android中的单例

    • Application
    public class MyApplication extends Application {
        private static MyApplication myApplication;
    
        public static MyApplication getIntstance() {
            return myApplication;
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            myApplication = this;
        }
    }
    
    • 单例模式引起的内存泄漏
      如果一个对象已经不需要使用了,而单例对象还持有该对象的引用,那么这个对象将不能被正常回收,这就导致了内存泄漏。
    public class Singletonleak {
        private static Context mContext;
    
        public static Singletonleak getInstance(Context context) {
    //        mContext=context;//错误写法
            mContext = context.getApplicationContext();//正确写法
            return SingletonLeakHolder.singletonleak;
        }
    
        private static class SingletonLeakHolder {
            private static final Singletonleak singletonleak = new Singletonleak();
        }
    
        public void show() {
            Toast.makeText(mContext, "zjy", Toast.LENGTH_SHORT).show();
        }
    }
    
    

    相关文章

      网友评论

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

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