美文网首页
单例模式——个人学习

单例模式——个人学习

作者: young_dreamer | 来源:发表于2016-06-25 16:01 被阅读65次

    单例模式

    一个类仅有一个实例,所有其他类对象共享该实例进行操作

    特点:只能由自己的公共方法创建一个实例,只对外提供该唯一实例

    应用场景:资源共享文件与控制资源的操作(如日志文件,应用配置,数据库连接池,线程池)

    应用实例:windows task manager,数据库连接池,OS的文件系统,回收站...

    实现方法:饿汉,懒汉(饱汉),双检索,静态内部类,枚举类

    • 懒汉模式只有需要单例时才去初始化实例,线程一般不安全
    • 饿汉模式在类加载阶段就将实例初始化完成,这样保证线程安全
    • 双检查模式,不是对这个方法进行synchronize,仅仅在实例化步骤前进行2次synchronize该类
    • 静态内部类,保证了线程安全,在内部类中实例化唯一实例,读取实例没有同步保证性能
    • 枚举模式,默认线程安全

    相关问题:

    • clone能否产生一个新的单例模式类的实例?
      不能,单例类必须是final的不能被继承,同时假如单例类继承于有clone方法的类,需要重写clone,是它抛出异常
    • 在getInstance()方法上同步有优势还是仅同步必要的块更优优势?
      由于锁有开销,因此仅同步必要的块(创建实例部分)就行了,其他时候仅仅是对实例的只读操作,保证性能
    • 双检索有什么缺点?
      需要防止初始化实例时,指令重排序,因此最好对指定变量使用volatile修饰,防止指令重排序(jdk5.0以后引入)
    • 如何获取更多的单例对象,如何防止?
      反射机制,防止的办法就是在构造函数中判断是第几次被调用,假如不是首次调用就立即抛出异常。还有一个办法就是使用枚举类模式实现单例
    Constructor con = Singleton. class. getDeclaredConstruction( ) ;
    con. setAccessible( true) ;
    //通过反射获取实例
    Singleton instance = ( Singleton) con. newInstance( ) ;
    

    枚举类型

    • 用来表示常量,作为switch的选择类型,继承自java.lang.Enum,因此不能继承其他类
    • 在类中添加其他方法,方法必须在实例后面,最后一个实例后需要接";"
    • 枚举集合:java.util.EnumSet,java.util.EnumMap

    实现方法实践

    //单例模式的实现方式
    
    // 懒汉(饱汉),一般没有对方法同步,多线程可能存在生成多个实例,优点是效率高,但是不安全,
    // 有时候直接类加载就初始化静态变量,浪费内存
    class Singleton{ 
        private static Singleton singleton;
        private Singleton(){};
    
        public static Singleton getInstance(){
            if(singleton == null){
                singleton = new Singleton();
            }
            return singleton;
        }
    }
    
    //饿汉,类加载就产生实例
    class Singleton{ 
        private static Singleton singleton = new Singleton();
        private Singleton(){};
    
        public static synchronized Singleton getInstance(){
            return singleton;
        }
    }
    
    //双重检测,对实例化块进行2次检验,使用同步
    class Singleton{ 
        private static volatile Singleton singleton;
        private Singleton(){};
    
        public static Singleton getInstance(){
            if(singleton == null){
                synchronized(Singleton.class){
                    if(singleton == null){
                        singleton = new Singleton();
                    }
                }
            }
            return singleton;
        }
    }
    
    //静态内部类,不用使用同步,线程安全.内部类私有性质保证只有getInstance能够调用它
    class Singleton{ 
        
        private static class SingletonHolder{
            private static final Singleton INSTANCE = new Singleton();
        } 
    
        private Singleton(){};
    
        public static Singleton getInstance(){
            return SingletonHolder.INSTANCE;
        }
    }
    
    //枚举类,默认线程安全,这种方式绝对防止反射调用私有构造器来破坏单例
    public enum Singleton{
        INSTANCE;
    
        private String name;
    
        public void dosomething(){
            doing...
        }
    }
    

    相关文章

      网友评论

          本文标题:单例模式——个人学习

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