栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

单例设计模式的理解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

单例设计模式的理解

单例模式的设计,需要分是否延迟加载.
从速度和反应时间角度来讲,非延迟加载(又称饿汉式)好;从资源利用效率上说,延迟加载(又称懒汉式)好。

单例模式的几种写法:
//第一种:非延迟加载单例类
//饿汉式, 这样写也是线程安全的.

`public class Singleton {  
    private Singleton() {}  
    private static final Singleton instance = new Singleton();  
    public static Singleton getInstance() {  
     return instance;  
    }  
}  `

//第二种:同步延迟加载

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

第三种:双重检测同步延迟加载
//instance 进行第二次检查,目的是避开过多的同步(因为这里的同步只需在第一次创建实例时才同步,一旦创建成功,以后获取实例时就不需要同获取锁了
//JDK5.0以后版本的instance为volatile才能使用:
//双重检测锁定失败的问题并不归咎于 JVM 中的实现 bug,而是归咎于 Java 平台内存模型,
// 内存模型允许所谓的“无序写入”,简单理解就是Java编译代码到JVM虚拟机时,是没有顺序的.

public class Singleton {  
   private volatile static Singleton instance = null;  
   private Singleton() {}  
   public static Singleton getInstance() {  
     if (instance == null) {  
         synchronized (Singleton.class) {// 1  
         if (instance == null) {// 2  
           instance = new Singleton();// 3  
         }  
       }  
    }  
    return instance;  
  }  
}  

第四种:使用ThreadLocal修复双重检测
//借助于ThreadLocal,将临界资源(需要同步的资源)线程局部化,具体到本例就是将双重检测的第一层检测条件 if (instance == null) 转换为了线程局部范围内来作。这里的ThreadLocal也只是用作标示而已,用来标示每个线程是否已访问过,如果访问过,则不再需要走同步块,这样就提高了一定的效率。但是ThreadLocal在1.4以前的版本都较慢,但这与volatile相比却是安全的。

public class Singleton {
    private static final ThreadLocal perThreadInstance = new ThreadLocal();
    private static Singleton singleton;

    private Singleton() {
    }

    public static Singleton getInstance() {
        if (perThreadInstance.get() == null) {
            // 每个线程第一次都会调用  
            createInstance();
        }
        return singleton;
    }

    private static final void createInstance() {
        synchronized (Singleton.class) {
            if (singleton == null) {
                singleton = new Singleton();
            }
        }
        perThreadInstance.set(perThreadInstance);
    }
}  

第五种:使用内部类实现延迟加载
//这种方式比起第一种方式, 不仅能保证线程安全,还能保证延迟加载.

public class Singleton {  
  private Singleton() {}  
  public static class Holder {  
   // 这里的私有没有什么意义  
   static Singleton instance = new Singleton();  
  }  
  public static Singleton getInstance() {  
   // 外围类能直接访问内部类(不管是否是静态的)的私有变量  
   return Holder.instance;  
  }  
}  

第六种: 使用枚举
//枚举在JVM虚拟机中, 默认是单例的, 并且是线程安全的. 这种方式也是最简单的

public class MyClass {
    static enum Singleton {
        instance;
    }
}

第七种: 使用容器
//这种使用容器的单例模式, 在Android系统服务里面有使用.

public class MyClass {
    static class SingletonManager{
        private static Map objectMap = new HashMap<>();
        public static void registerService(String key,Object instance) {
            if (!objectMap.containsKey(key)) {
                objectMap.put(key, instance);
            }
        }

        public static Object getService(String key) {
            return objectMap.get(key);
        }
    }
}

参考资料: https://www.iteye.com/topic/652440

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/425256.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号