zoukankan      html  css  js  c++  java
  • 创建型模式————单例模式(2.1)

    单例模式定义

    在软件系统中,一个类只有一个实例对象。(该类只提供一个取得实例的静态方法)


    推荐使用的三种单例模式

    • DoubleCheck
    • 静态内部类
    • 枚举

    1.DoubleCheck 双重检查


    特点:效率高,线程安全,延迟加载。
    class DoubleCheck
    {
        private static volatile DoubleCheck instance;
    
        private DoubleCheck(){}
    
        public static DoubleCheck getInstance()
        {
            /*
            DoubleCheck如何实现?线程安全和效率提升
            
            在多线程的环境下,假设线程A直接进入#2,实例化对象。
            且实例化方法外用synchronized修饰,所以是线程安全的。
            当线程A实例化对象结束,对象instance已经被创建,执行到#1的线程将会直接调到#3,返回instance
            
            且DoubleCheck实现了延迟加载(new在方法里)
             */
            if(instance==null)                               //#1
            {
                synchronized (DoubleCheck.class)             //#2
                {
                    if(instance==null)
                    {
                        instance = new DoubleCheck();        //#3
                    }
                }
            }
            return instance;
        }
    }
    
    
    public class Operation
    {
        public static void main(String[] args) {
            DoubleCheck doubleCheck1 = DoubleCheck.getInstance();
            DoubleCheck doubleCheck2 = DoubleCheck.getInstance();
    
            System.out.println(doubleCheck1.hashCode());
            System.out.println(doubleCheck2.hashCode());
    
    
        }
    }
    

    2.静态内部类

    特点:通过JVM类加载避免了线程安全问题,延迟加载,效率高。

    class StaticClassInner {
    
        private StaticClassInner() {}
    
    
    
        /*
         使用静态内部类,实现了延迟加载
         调用getInstance()方法时,才会加载StaticClassInnerInstance。
    
         通过JVM类加载线程安全的机制,避免了线程不安全。
    
         */
        private static class StaticClassInnerInstance {
            private static final StaticClassInner INSTANCE = new StaticClassInner();
        }
    
        public static StaticClassInner getInstance() {
            return StaticClassInnerInstance.INSTANCE;
        }
    }
    
    public class Operation
    {
        public static void main(String[] args) {
            StaticClassInner doubleCheck1 = StaticClassInner.getInstance();
            StaticClassInner doubleCheck2 = StaticClassInner.getInstance();
    
            System.out.println(doubleCheck1.hashCode());
            System.out.println(doubleCheck2.hashCode());
    
    
        }
    }
    

    3.枚举

    Effective Java作者Josh Bloch推荐。

    enum Hq
    {
        INSTANCE;
    
        public void printf()
        {
            System.out.println("ins");
        }
    }
    
    public class Operation
    {
        public static void main(String[] args) {
            Hq hq = Hq.INSTANCE;
            Hq hqq = Hq.INSTANCE;
    
            System.out.println(hq.hashCode());
            System.out.println(hqq.hashCode());
        }
    }
    

    饿汉式的延迟加载问题(可用)


    如果创建的对象一定会被使用,那么可以忽略内存浪费的问题。

    class SingleTom
    {
        private SingleTom()
        { }
    
        /*
        在静态常量中实例化对象,无法实现延迟加载,如果对象未被使用,会造成内存浪费。(#1)
        无线程安全问题
    
        将实例化对象放于静态代码块中并无实际作用
         */
        private final static SingleTom instance;  // = new SingleTom();#1
    
        static  //#2
        {
            instance=new SingleTom();
        }
    
    
        public static SingleTom getInstance()
        {
            return instance;
        }
    }
    
    public class Operation
    {
        public static void main(String[] args) {
            SingleTom hq = SingleTom.getInstance();
            SingleTom hqq = SingleTom.getInstance();
    
            System.out.println(hq.hashCode());
            System.out.println(hqq.hashCode());
        }
    }
    

    懒汉式的线程安全问题(不可用)


    class Singletom {
    
        private static Singletom singleton;
    
        private Singletom() {}
    
        /*
        线程不安全:
    
        调用getInsyance()方法时,如果同时有多个线程同时进入到#1
        就会创建多个实例对象
    
        倘若在方法上加上syn关键字,线程同步问题解决,但效率大大降低
        
        doublecheck大概就是在这种纠结下选择用两次if(singleton == null)来控制线程同步和效率问题
    
         */
        public static /*synchronized*/ Singletom getInstance() {
            if (singleton == null) {                   //#1
                singleton = new Singletom();
            }
            return singleton;
        }
    }
    
    public class Operation
    {
        public static void main(String[] args) {
            Singletom hq = Singletom.getInstance();
            Singletom hqq = Singletom.getInstance();
    
            System.out.println(hq.hashCode());
            System.out.println(hqq.hashCode());
        }
    }
    

    参考文档:

    单例模式的八种写法比较

  • 相关阅读:
    简单三步给MM美白
    人物扣图抽出法
    Photoshop用抽出法抠婚纱图技巧实例集合
    十余种漂亮照片边框简单制作技巧
    如何安装knockout 2.0
    色阶去水印法
    PS合成古典的水墨舞者
    在photoshop中,从1寸到24寸的大小是多少
    常用Smarty变量操作符
    discuz代码分析一 从common.inc.php开始
  • 原文地址:https://www.cnblogs.com/noneplus/p/11336752.html
Copyright © 2011-2022 走看看