zoukankan      html  css  js  c++  java
  • 设计模式--单例模式

    确保一个类只有一个实例,并提供全局访问点。私有化构造器,静态方法和静态变量

    管理共享资源:线程池、缓存、偏好设置

    全局变量和单例模式 :急切实例化VS延迟实例化

    1.懒汉式

    public class Singleton {
        private static Singleton instance = null;
        private Singleton(){
        }
        public static Singleton getInstance(){
            if(instance == null){
                instance = new Singleton();
            }
            return instance;
        }
    }

    线程安全版本:

    1.使用同步方法(synchronized关键字),性能差

    public class Singleton {
        private static Singleton instance = null;
        private Singleton(){
        }
        public static synchronized Singleton getInstance(){
            if(instance == null){
                instance = new Singleton();
            }
            return instance;
        }
    }

    2.使用饿汉式(急切实例化,JVM加载时,就会创建唯一的实例)

    public class Singleton {
        //私有化成员变量
        private static Singleton instance = new Singleton();
        //私有化构造器
        private Singleton(){
        }
        //只提供public的getter方法,但是没有setter方法
        public static Singleton getInstance(){
            return instance;
        }
    }

    3.用“双重检查加锁”,来减少使用同步

    public class Singleton{
        private volatile static Singleton instance = null;
        private Singleton(){
        }
        public static Singleton getInstance(){
            if(instance == null) {
                synchronized (Singleton.class) {
                    if (instance == null) {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
    在懒汉式的线程安全版本中,也可能存在问题
    * 在Java指令中创建对象和赋值操作是分开进行的,
    * 也就是说instance = new Singleton();语句是分两步执行的。
    * 但是JVM并不保证这两个操作的先后顺序,也就是说有可能JVM会为新的Singleton实例分配空间,
    * 然后直接赋值给instance成员,然后再去初始化这个Singleton实例。这样就可能出错了,
    * 我们以A、B两个线程为例:
    a>A、B线程同时进入了第一个if判断
    b>A首先进入synchronized块,由于instance为null,所以它执行instance = new Singleton();
    c>由于JVM内部的优化机制,JVM先画出了一些分配给Singleton实例的空白内存,
    并赋值给instance成员(注意此时JVM没有开始初始化这个实例),然后A离开了synchronized块。
    d>B进入synchronized块,由于instance此时不是null,
    因此它马上离开了synchronized块并将结果返回给调用该方法的程序。
    e>此时B线程打算使用Singleton实例,却发现它没有被初始化,于是错误发生了。
    * 采用静态内部类的方法来创建
    * 单例模式使用内部类来维护单例的实现,JVM内部的机制能够保证当一个类被加载的时候,
    * 这个类的加载过程是线程互斥的。这样当我们第一次调用getInstance的时候,
    * JVM能够帮我们保证instance只被创建一次,并且会保证把赋值给instance的内存初始化完毕,
    * 这样我们就不用担心上面的问题。同时该方法也只会在第一次调用的时候使用互斥机制,
    * 这样就解决了低性能问题
    public class Singletone3 {
        /*私有化构造器*/
        private  Singletone3(){
        }
        /*使用内部类来维护单例模式*/
        private static class SingletoneFactory{
            private static Singletone3 instance = new Singletone3();
    
        }
        /*获取实例*/
        public static Singletone3 getInstance(){
            return SingletoneFactory.instance;
        }
    }
    

      




  • 相关阅读:
    Word Embedding理解
    几种简单的主题模型(生成模型)
    BTM学习小记
    LDA学习小记
    word2vec训练好的词向量
    java带字符编码编译
    web安全领域常见的攻击方式
    宝塔webhook布置gitee自动同步服务端
    unity3d学习路线
    缩略图含裁剪文件
  • 原文地址:https://www.cnblogs.com/SkyeAngel/p/9181640.html
Copyright © 2011-2022 走看看