8种 单例设计模式( 三 )


a. memory = allocate() //分配内存b. ctorInstanc(memory) //初始化对象c. instance = memory //设置instance指向刚分配的地址
上面的代码在编译运行时,可能会出现重排序从a-b-c排序为a-c-b 。在多线程的情况下会出现以下问题 。当线程A在执行第5行代码时,B线程进来执行到第2行代码 。假设此时A执行的过程中发生了指令重排序,即先执行了a和c,没有执行b 。那么由于A线程执行了c导致指向了一段地址,所以B线程判断不为null,会直接跳到第6行并返回一个未初始化的对象
优缺点:
-Check概念是多线程开发中常使用到的,如代码中所示,我们进行了两次if ( == null)检查,这样就可以保证线程安全了 。
这样,实例化代码只用执行一次,后面再次访问时,判断if ( == null),直接实例化对象,也避免的反复进行方法同步 。
这种方法线程安全;延迟加载;效率较高
在实际开发中,推荐使用这种单例设计模式
七、静态内部类
public class SingletonMode07 {private SingletonMode07(){}private static class SingletonModeInstance{private static final SingletonMode07 INSTANCE = new SingletonMode07();}public static SingletonMode07getInstance(){return SingletonModeInstance.INSTANCE;}}
优缺点:
这种方式采用了类装载的机制来保证初始化实例时只有一个线程 。
静态内部类方式在类被装载时并不会立即实例化,而是在需要实例化时,调用方法,
才会装载e类,从而完成的实例化 。
类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的 。
这种方式避免了线程不安全,利用静态内部类特点实现延迟加载,效率高
【8种单例设计模式】推荐使用这种方法 。
八、枚举
public enum SingletonMode08 {INSTANCE("单例模式",123456);private String name;private int number;SingletonMode08(String name, int number) {this.name = name;this.number = number;}@Overridepublic String toString() {return "SingletonMode08{" +"name='" + name + '\'' +", number=" + number +'}';}}
优缺点:
这借助JDK1.5中添加的枚举来实现单例模式 。不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象 。
这种方式是 Java作者Josh Bloch 提倡的方式
这种方式推荐使用
单例设计模式小结
单例模式保证了 系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能
当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用new
单例模式使用的场景:需要频繁的进行创建和销毁的对象、创建对象时耗时过多或耗费资源过多(即:重量级对象),
但又经常用到的对象、工具类对象、频繁访问数据库或文件的对象(比如数据源、工厂等)
单例模式 - 应用场景