zoukankan      html  css  js  c++  java
  • 创建型设计模式之单例模式


    单例模式使用场景:
    需要频繁和创建和销毁的对象
    创建对象耗时过多或消耗资源过多,即重量级对象,但又经常用到的对象
    工具类对象,频繁访问数据库或文件的对象(如数据源、session工厂等)
    Runtime就是精典的饿汉单例模式应用
    public class Runtime {
        private static Runtime currentRuntime = new Runtime();
    
        /**
         * Returns the runtime object associated with the current Java application.
         * Most of the methods of class <code>Runtime</code> are instance
         * methods and must be invoked with respect to the current runtime object.
         *
         * @return  the <code>Runtime</code> object associated with the current
         *          Java application.
         */
        public static Runtime getRuntime() {
            return currentRuntime;
        }
    
        /** Don't let anyone else instantiate this class */
        private Runtime() {}
    
    
    public static void main(String[] args) {
       //精典的饿汉模式
      Runtime.getRuntime();

    Singleton s1 = Singleton.Instance;
    Singleton s2= Singleton.Instance;
    System.out.println(s1==s2);
    System.out.println(s1.hashCode());
    System.out.println(s2.hashCode());
    s1.sayHello();
    }
    /**
     * 饿汉式(静态变量)
     * 优点:写法简单,在类装载时完成实例化,避免了线程同步问题
     * 缺点:装载时完成实例化,没有达到懒加载效果,如果不使用这个实例,造成内存浪费。
     * 结论:可用,会造成内存浪费。
     */
    public class Singleton {
    
        //1. 构造器私有化,外部不能new
        private  Singleton(){
    
        }
    
        //2. 内部创建实类对象
        private final static Singleton instance = new Singleton();
    
        //3. 对外提供静态方法,返回对象实例
        public static Singleton getInstance(){
            return instance;
        }
    }
    
    /**
     * 饿汉式(静态代码块)
     * 优点:写法简单,在类装载时完成实例化,避免了线程同步问题
     * 缺点:装载时完成实例化,没有达到懒加载效果,如果不使用这个实例,造成内存浪费。
     * 结论:可用,会造成内存浪费。
     */
    public class Singleton {
    
        //1. 构造器私有化,外部不能new
        private  Singleton(){
    
        }
    
        //2. 静态代码块中创建实类对象
        private final static singleton.type2.Singleton instance;
        static{
            instance = new singleton.type2.Singleton();
        }
    
        //3. 对外提供静态方法,返回对象实例
        public static singleton.type2.Singleton getInstance(){
            return instance;
        }
    }
    /**
     * 懒汉式(线程不安全)
     * 只能在单线程下使用
     */
    public class Singleton {
        private Singleton(){};
    
        private static Singleton instance;
    
        public static Singleton GetInstance(){
            if(instance==null){
                instance= new Singleton();
            }
            return instance;
        }
    }
    
    
    /**
     * 懒汉式(同步方法解决线程安全)
     * 效率低
     */
    public class Singleton {
        private static Singleton instance;
        private Singleton(){};
        public static synchronized Singleton getInstance(){
            if(instance==null){
                instance=new Singleton();
            }
            return instance;
        }
    }
    
    /**
     * 同步代码块解决线程安全
     * 不推荐
     */
    public class Singleton {
        private static Singleton instance;
        private Singleton(){};
        public static Singleton getInstance(){
            if(instance==null){
                synchronized (Singleton.class){
                    instance=new Singleton();
                }
            }
            return instance;
        }
    }
    /**
     * 双重检查
     * 线程安全,延迟加载,效率较高
     * 推荐使用
    
     双重校验锁法会有怎样的情景:
     * STEP 1. 线程A访问getInstance()方法,因为单例还没有实例化,所以进入了锁定块。
     * STEP 2. 线程B访问getInstance()方法,因为单例还没有实例化,得以访问接下来代码块,而接下来代码块已经被线程1锁定。
     * STEP 3. 线程A进入下一判断,因为单例还没有实例化,所以进行单例实例化,成功实例化后退出代码块,解除锁定。
     * STEP 4. 线程B进入接下来代码块,锁定线程,进入下一判断,因为已经实例化,退出代码块,解除锁定。
     * STEP 5. 线程A初始化并获取到了单例实例并返回,线程B获取了在线程A中初始化的单例。
     * 理论上双重校验锁法是线程安全的,并且,这种方法实现了lazyloading。
     */
    public class Singleton {
        private static volatile Singleton instance;
        private Singleton(){};
        public static Singleton getInstance(){
            if(instance==null){
                synchronized (Singleton.class){
                    if(instance==null){
                        instance=new Singleton();
                    }
                }
            }
            return instance;
        }
    }
    
    /**
     * 静态内部类不会在单例加载时就加载,而是在调用getInstance()方法时才进行加载,
     * 达到了类似懒汉模式的效果, *而这种方法又是线程安全的。
     */
    public class Singleton {
    
        private static class SingletonInstantce{
            private final static Singleton instance = new Singleton();
        }
    
        private Singleton(){
    
        }
    
        public static Singleton getInstance(){
            return SingletonInstantce.instance;
        }
    }
    
    /**
     * 枚举法
     */
    public enum Singleton {
        Instance;
        public void sayHello(){
            System.out.println("hello");
        }
    }
  • 相关阅读:
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
  • 原文地址:https://www.cnblogs.com/huangzhen22/p/14487132.html
Copyright © 2011-2022 走看看