zoukankan      html  css  js  c++  java
  • 从单例模式说起

    单例模式是我们比较常用的设计模式,玩好单例模式也会涉及到很多java基础知识。
    单例作为全局性实例,在多线程情况下全局共享的变量会变得非常危险。

    双重检测:

    双重检测是比较常用的一种实现方式:

    public class Singleton {
        public static final volatile Singleton singleton = null;
        private Singleton(){}
        public static Singleton getInstance(){
            if(singleton == null){ 
               synchronize (Singleton.class){
                   if( singleton == null ) { 
                       singleton = new Singleton();
                   }
            }
            return singleton;
        }
    }
    

    如果不用volatile修饰,多线程执行到 singleton == null 时,多个实例会被创建出来,就可能造成内存泄露问题。

    当然你可以说可以用互斥同步的方式进行,但是我们做了同步,多线程的操作就变成了串型了,效率会很低,因为创建对象其实只需要一次,但是后面的读取都需要同步了。

    还有一个原因,在jvm编译器可能会对指令进行重拍和优化,就是判断singleton == null的判断顺序可能无法保证。
    于是我们将变量用volatile修饰,这个变量就不会在多线程中存在副本,都必须从主内存读取,同时避免了指令重拍。

    当两个线程执行完第一个 singleton == null 后等待锁, 其中一个线程获得锁并进入synchronize后,实例化了,然后退出释放锁,另外一个线程获得锁,进入又想实例化,会判断是否进行实例化了,如果存在,就不进行实例化了。

    静态内部类(懒汉模式)

    一个延迟实例化的内部类的单例模式,一个内部类的容器,调用getInstance时,JVM加载这个类

    public final class Singleton {
        private static class SingletonHolder {
            static final Singleton INSTANCE =  new Singleton();
        }
     
        private Singleton() {}
        public static final Singleton getInstance() {
            return SingletonHolder.INSTANCE;
        }
     }
    

    由于SingleHolder是私有的,除了getInstance()之外没有方法可以访问它,只有在getInstance()被调用时才会真正创建,

    首先,其他类在引用这个Singleton的类时,只是新建了一个引用,并没有开辟一个的堆空间存放(对象所在的内存空间)。
    接着,当使用Singleton.getInstance()方法后,Java虚拟机(JVM)会加载SingletonHolder.class(JLS规定每个class对象只能被初始化一次),并实例化一个Singleton对象。

    缺点:

    需要在Java的另外一个内存空间(Java PermGen 永久代内存,这块内存是虚拟机加载class文件存放的位置)占用一个大块的空间。


  • 相关阅读:
    sql2005新特性 for xml , outer apply ,多行转成单列方法
    数据库备份还原到指定时间
    在 64 位版本的 Windows 上,如何在 32 位版本的 ASP.NET 1.1 和 64 位版本的 ASP.NET 2.0 之间切换
    人事管理系统的一般功能需求
    转支持非主键排序的SQL存储过程
    正则表达式删除指定的HTML 标签
    PAZU 4Fang WEB 打印控件
    ASP.NET木马及Webshell安全解决方案
    vue3+element 父组件子组件传值
    彻底理解01背包问题
  • 原文地址:https://www.cnblogs.com/xiguain/p/9237403.html
Copyright © 2011-2022 走看看