(3/23)单例设计模式
来源:互联网 发布:股票赢家软件 编辑:程序博客网 时间:2024/05/18 02:08
顾名思义,就是保证在JVM中只有实例对象存在
单例设计模式,应用很广,优点如下:
1、当某个对象比较大,且应用很频繁,采用单例就可以节省很大的系统开销
2、new一次后,就不需要再new了,降低了系统内存的使用频率,减轻垃圾回收机制的工作
以上实现方式,一旦处于多线程环境下,就会出现安全隐患,A,B两个线程,A判断s==null后,正准备new,还没new完,就切换到B线程,B线程new完后,切回A线程,继续new,以致出现隐患
初级解决方案:
增加线程锁,保证安全.
此方法,虽然解决了安全问题,但是牺牲的代价有点,因为多线程不安全的问题,只在判断实例引用为null后去new
实例对象过程中发生的,所以我们只需保证第一创建对象时,线程安全即可
改进后:
用内部类可以进一步维护单例。
总结:
1.单例设计模式看似简单,但实现起来并不简单,懒汉式这一方式一定要谨慎使用,开发不使用,但是一定要会,面试
2.synchronized的使用必须成分考虑,让它呆在应该在的地方,不要顾此失彼,解决了安全,却牺牲了效率。
单例设计模式,应用很广,优点如下:
1、当某个对象比较大,且应用很频繁,采用单例就可以节省很大的系统开销
2、new一次后,就不需要再new了,降低了系统内存的使用频率,减轻垃圾回收机制的工作
3、某些情况下,需要一个类来控制全局时,就需要单例。(一个国家只能有一个最高领导人,多了话,听谁的?)
一个简单的懒汉式:
public class Single {private static Single s = null;//私有静态实例,防止被外部引用,初始null,延迟加载private Single(){}//返回实例public static Single getInstace(){if(s==null)s = new Single();return s;}//如果对象需要被用于序列化,这样就可以对象在序列化前后保持一致public Object readResolve(){return s;}}
以上实现方式,一旦处于多线程环境下,就会出现安全隐患,A,B两个线程,A判断s==null后,正准备new,还没new完,就切换到B线程,B线程new完后,切回A线程,继续new,以致出现隐患
初级解决方案:
增加线程锁,保证安全.
<span style="white-space:pre"></span>public class Single {private static Single s = null;private Single(){}public synchronized static Single getInstace(){if(s==null)s = new Single();return s;}public Object readResolve(){return s;}}
此方法,虽然解决了安全问题,但是牺牲的代价有点,因为多线程不安全的问题,只在判断实例引用为null后去new
实例对象过程中发生的,所以我们只需保证第一创建对象时,线程安全即可
改进后:
public static Single getInstace(){if(s==null){//解决效率synchronized(Single.class){if(s == null)//解决安全问题s = new Single();}}return s;}
将 synchronized 加在了内部,也就是说当调用的时候是不需要加锁的,只有在 s 为 null, 并创建对象的时候才需要加锁, 性能有一定的提升。
貌似解决了问题,但是有可能出现隐患。
在 Java 指令中创建对象和赋值操作是分开进行的,也就是说s = new Single();语句是分两步执行的。
但是JVM却不是保证两者的顺序,有可能JVM先分配空间,再赋值给s,然后在初始化Single实例,这样就会出现问题
比如:A , B 两个线程
1.A,B同时通过第一个if判断,进入
2.A线程先获得锁对象,s == null , 执行s = new Single();
3.但是,JVM线程分配Single实例的空白内存,并赋值s,但是还有初始化s,A线程就离开synchronized
4.B线程拿到锁对象,但是此时的s!=null,所以B线程离开
5.那么调用getInstace()的程序,因为没有初始化,出现问题
所以:多线程环境下,懒汉式的隐患很难根除,所以开发一般不会用,采用用饿汉式
(面试肯定是问懒汉式,技术含量高)
饿汉式
public class Single {private static final Single s = new Single();public static Single getInstance(){return Single.s;}}
用内部类可以进一步维护单例。
public class Single {private Single(){}public static class SingleChild{private static Single s = new Single();}public static Single getInstance(){return SingleChild.s;}public Object ReadResolve(){return getInstance();}}
总结:
1.单例设计模式看似简单,但实现起来并不简单,懒汉式这一方式一定要谨慎使用,开发不使用,但是一定要会,面试
2.synchronized的使用必须成分考虑,让它呆在应该在的地方,不要顾此失彼,解决了安全,却牺牲了效率。
0 0
- (3/23)单例设计模式
- 23中设计模式单例模式
- 23种设计模式-单例模式
- 23种设计模式~单例模式
- 23种设计模式-单例模式
- 23种设计模式-----单例模式
- 23种设计模式-单例模式
- 设计模式 1-23 单例模式
- 设计模式 1-23 单例模式
- 23种设计模式-单例模式
- 设计模式3 - 单例模式Singleton
- 设计模式系列3-单例模式
- java设计模式(3)---单例模式
- 设计模式(3): 单例模式
- <设计模式3>单例模式
- 设计模式--[3]单例模式
- 设计模式(3)-单例模式
- 设计模式3-单例模式
- HDU4324 Triangle LOVE【拓扑排序】
- eyetribe_API Reference
- android中合理利用反射
- Eyetribe_Language Tutorials C++
- 好好学习,写写报告
- (3/23)单例设计模式
- 如何查询特殊字符 主要是% _
- git教程第一篇:简单介绍配置
- Struts2——Tags
- 禁忌搜索算法
- PHPEXCEL结合MYSQL+PHP实现数据库数据导出EXCEL实例
- unity学习之总结
- 简单讲一下C语言连接MySQL数据库
- 图深度优先搜索之能否到达终点