设计模式之单例模式的理解
概念
构造方法私有化 防止外部直接new对象
类的内部创建对象
向外暴露一个静态的公共方法
实现单例模式的八种方式
静态常量饿汉式
优缺点说明
1,优点:这种写法比较简单,就是在类装载的时候就完成实例化,避免了线程同步问题
2,缺点,在类装载的时候就完成实例化,没有达到懒加载的效果,如果从开始至终未使用这个实例,则会造成内存浪费
3,这种方式基于classloader机制避免了很多线程同步的问题,不过,instance在类装载时就实例化,在单例模式中大多数都是调用getInstance方法,但是导致类装载的原因有多种,因此不能确定有其他的方式或其他的静态方法 导致类装载,这个时候初始化instance就没有懒加载的效果
4,这种单例模式可用,可能会造成内存浪费
静态代码块饿汉式
1,这种方式和上面的方式其实类似,只不是将类实例化的过程放在了静态代码块中,也是在类装载的时候,就执行静态代码块中的代码,初始化的实例,优缺点跟上面一样
2,这种单例模式可用,可能会造成内存浪费
线程不安全懒汉式
1,起到了懒加载的效果,但是只能在单线程下使用
2,如果在多线程下,一个线程进入了if(single3 == null)判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例,所以在多线程环境下不可使用这种方式
3,在实际开发中,不推荐这种方式
线程安全懒汉式
1,解决了线程不安全问题
2,效率太低了,每个线程在想获得类的实例时候,执行了getInstance()方法都要进行同步,而其实这个方法只执行一次实例化就够了,后面的想获得实例直接return就行了,方法进行同步效率太低
3,在实际开发中,不推荐,多线程情况下,效率过低
同步代码块懒汉式
1,这种方式,本意是相对第四种实现方式的改进,因为前面同步方法效率太低,改为同步产生实例化的的代码块
2,但是这种同步并不能起到线程同步的作用,跟第3种实现方式遇到的情形一致,假如一个线程进入了if(singleton==null)判断语句块,还未来得及外下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例
3,在实际开发中,不推荐这种方式
DoubleCheck(双重检查式)
1,双重检查式概念是多线程开发中经常使用到的,如代码所示,我们进行了两次判断single3是否等于null 这样就可以保证线程安全
2,这样,实例化代码只执行了一次,后面再次访问时,判断if(single3==null)直接return实例化对象,也避免了反复进行方法同步
3,线程安全,延迟加载,效率较高
4,推荐使用这种单例模式
静态内部类
1,这种方式采用了类装载的机制来保证初始化实例只有一个线程
2,静态内部类方式在类被装载时并不会立即初始化,而是在需要实例化时,调用getInstance方法,才会装载到SingletonInstance类,从而完成Singleton的实例化
3,类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程无法进入的
4,避免了线程不安全,利用静态内部类特点实现延迟加载,效率高
5,推荐使用
枚举方式
1,这借助JDK1.5中添加的枚举来实现单例模式,不仅避免了线程同步问题,而且还能防止反序列化重新创建新的对象
2,这种方式是Effective Java作者josh Bloch 提倡的方式
3,推荐使用
单例模式注意事项
1,单例模式保证了,系统内存中该类只有一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能
2,当想实例化一个单例类的时候,必须要记住使用相应的获取对象的办法,而不是使用new
3,单例模式使用的场景,需要频繁的进行创建和销毁的对象,创建对象时销毁时过多或消耗资源过多(重量级对象),但又经常使用到的对象,工具类对象,频繁访问数库或文件对象 如:数据源 session工厂等
学习来源:B站韩顺平
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/112564.html