美文网首页学习
设计模式一:单例模式

设计模式一:单例模式

作者: 神气小风 | 来源:发表于2021-03-23 23:37 被阅读0次

    八种写法:

    1)饿汉式(静态常量)
    2)饿汉式(静态代码块)
    3)懒汉式(线程不安全)
    4)懒汉式(线程安全,同步方法)
    5)懒汉式(线程安全,同步代码块)
    6)双重检查
    7)静态内部类
    8)枚举

    饿汉式:在类加载的时候就创建实例对象,没有节约内存。
    懒汉式:在使用的时候才去创建实例对象,节省了内存。
    ---------------------------------------------------------------

    1)饿汉式(静态常量)

    public class SingletonOne {
    
        private SingletonOne(){}
    
        private final static SingletonOne instance = new SingletonOne();
    
        public static SingletonOne getInstance() {
            return instance;
        }
    
    }
    
    优点:写法简单,在类加载的时候就完成了实例化。避免了线程同步问题。
    缺点:在类加载的时候就完成了实例化,没有达到懒加载的效果。
    android中的application中可以使用此种方式。(实例化时要在onCreate()方法中进行)
    ---------------------------------------------------------------

    2)饿汉式(静态代码块)

    public class SingletonTwo {
    
        private SingletonTwo(){}
    
        private static SingletonTwo instance;
    
        static {
            instance = new SingletonTwo();
        }
    
        public static SingletonTwo getInstance() {
            return instance;
        }
    }
    
    优缺点同第一种写法
    ---------------------------------------------------------------

    3)懒汉式(线程不安全)

    public class SingletonThree {
    
        private static SingletonThree instance;
    
        private SingletonThree(){}
    
        /**
         * 只有在用的时候才调用这个方法,才会创建实例对象
         */
        public static SingletonThree getInstance() {
            if(instance == null) {
                // 多线程情景下,会有多个线程执行到此处
                instance = new SingletonThree();
            }
            return instance;
        }
    }
    
    优点:懒加载
    缺点:线程不安全
    可以在确保是单线程的场景下使用
    ---------------------------------------------------------------

    4)懒汉式(线程安全,但是速度慢)

    public class SingletonFour {
    
        private static SingletonFour instance;
    
        private SingletonFour(){}
    
        /**
         * 加入synchronized后,每次调用都会同步,所以速度慢
         */
        public static synchronized SingletonFour getInstance() {
            if(instance == null) {
                instance = new SingletonFour();
            }
            return instance;
        }
    }
    
    优点:懒加载,线程安全
    缺点:速度慢
    不推荐使用
    ---------------------------------------------------------------

    5)懒汉式(线程不安全,同步代码块)

    public class SingletonFive {
    
        private static SingletonFive instance;
    
        private SingletonFive(){}
    
        public static SingletonFive getInstance() {
            if(instance == null) {
                // 多线程情景下,还是会有多个线程进入到这行,只不过会并行而已
                synchronized (SingletonFive.class) {
                    instance = new SingletonFive();
                }
            }
            return instance;
        }
    }
    
    优点:懒加载
    缺点:线程不安全
    不推荐使用
    ---------------------------------------------------------------

    6)双重检查

    public class SingleonSix {
    
        private static volatile SingleonSix instance;
    
        private SingleonSix(){}
    
        public static SingleonSix getInstance() {
            if(instance == null) {
                // 多线程场景下,会有多个线程进入到这行,但是下一行只有第一个能进去
                synchronized (SingleonSix.class) {
                    if(instance == null) {
                        instance = new SingleonSix();
                    }
                }
            }
            return instance;
        }
    }
    
    优点:懒加载,线程安全,速度较快
    推荐使用
    ---------------------------------------------------------------

    7)静态内部类

    public class SingleonSeven {
    
        private SingleonSeven(){}
    
        private static class SingletonInstance {
            private static final SingleonSeven INSTANCE = new SingleonSeven();
        }
    
        public static SingleonSeven getInstance() {
            return SingletonInstance.INSTANCE;
        }
    }
    
    说明:采用类加载的机制来保证初始化实例时只有一个线程。静态内部类SingletonInstance 在类SingleonSeven装载的时候不会立即实例化。只有调用getInstance()方法时才会实例化。类的静态属性只有在第一次加载类的时候才初始化。这样JVM保证了线程的安全,在类进行初始化时,别的线程是无法进入的。
    线程安全,懒加载,推荐使用
    ---------------------------------------------------------------

    8)枚举

    public enum SingleonEight {
        
        INSTANCE;
    
        public void sayHello() {
            System.out.println("hello");
        }
    }
    
    说明: 枚举是确保单例的。
    ---------------------------------------------------------------

    jdk源码中的单例使用举例:Runtime .java

    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() {}
        ......
    }
    

    Android源码中的使用:WindowManagerService .java

    public class WindowManagerService extends IWindowManager.Stub
                implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
    
            //......
    
            private static WindowManagerService sInstance;
            static WindowManagerService getInstance() {
                return sInstance;
            }
    
            public static WindowManagerService main(final Context context, final InputManagerService im,
                                                    final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore,
                                                    WindowManagerPolicy policy) {
                DisplayThread.getHandler().runWithScissors(() ->
                        sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,
                                onlyCore, policy), 0);
                return sInstance;
            }
            //......
        }
    
    总结:
    单例模式保证了系统内存中只存在该类的一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能。
    ---------------------------------------------------------------
    单例模式和静态方法的场景:
    一般静态方法都是没有任何其他的外部属性,只是一个工具类中的方法。而单例是需要外部属性的。

    相关文章

      网友评论

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

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