设计模式之单例模式
来源:互联网 发布:质量好的挎包淘宝店 编辑:程序博客网 时间:2024/05/22 03:49
单例模式
单例模式:确保一个类只有一个实例,并提供一个全局访问点。
单例模式用来创建独一无二的,只能有一个实例的对象的入场券。
问:这样做有什么好处呢?
答:有一些对象其实我们只需要一个,比方说:线程池(threadpool)、缓存(cache)、对话框、处理偏好设置和注册表(registry)的对象、日志对象,充当打印机、显卡等设备的驱动程序对象。事实上,这类对象只能有一个实例,如果制造出多个实例,就会导致许多问题产生,例如:程序的行为异常、资源使用过量,或者是不一致的结果。
经典的单例模式实现:
package com.my.singleton;public class Singleton { //利用一个静态变量来记录Singleton类的唯一实例。 private static Singleton uniqueInstance; //把构造器声明为私有的,只有从Singleton类内才可以调用构造器。 private Singleton(){} public static Singleton getInstance(){//用getInstance()方法实例化对象, // 并返回这个实例。 if(uniqueInstance==null){ //如果这个类不存在,我们就用私有的构造器产生一个Singleton实例并 // 把它赋值给uniqueInstance uniqueInstance = new Singleton(); } return uniqueInstance; }}单例模式类图:
现在我们的单例代码还有一个地方没有考虑到,那就是对于多线程的处理。多个线程执行时就无法保证对象的唯一性,如果同一时间有多个线程进入if语句当中,就有可能产生多个对象。这个时候我们只需要把getInstance()方法变成同步(synchronized)方法,多线程就可以轻易的解决了。
package com.my.singleton;public class Singleton { private static Singleton uniqueInstance; private Singleton(){} //通过增加synchroinzed关键字到getInstance()方法中,我们迫使每个线程在进入这个方法之前,要先等候别的线程离开该方法。
//也就是说,不会有两个线程可以同时进入这个方法。 public static synchronized Singleton getInstance(){ if(uniqueInstance==null){ uniqueInstance = new Singleton(); } return uniqueInstance; }}现在同步的问题解决了,但同时又会产生另一个问题:同步会导致性能降低。只有第一次执行此方法时,才真正需要同步。换句话说,一旦设置好uniqueInstance变量,就不再需要同步这个方法了。之后每次调用这个方法,同步是一种累赘。
解决办法:
1.使用“急切”的方式来创建实例,而不用延迟实例化的做法
package com.my.singleton;public class Singleton { //在静态初始化器(static initializen)中创建单例。这段代码保证了线程的安全。 private static Singleton uniqueInstance = new Singleton(); private Singleton(){} public static synchronized Singleton getInstance(){ return uniqueInstance; }}我们依赖JVM在加载这个类时马上创建此唯一的单例。JVM保证在任何线程访问uniqueInstance静态变量之前,一定先创建此实例。
2.用“双重检查加锁”,在getInstance()中减少使用同步
package com.my.singleton;public class Singleton { //volatile关键词确保:当uniqueInstance变量被初始化成Singleton实例时,多个线程可以 //正确的处理uniqueInstance变量。 private volatile static Singleton uniqueInstance; private Singleton(){} public static synchronized Singleton getInstance(){ if(uniqueInstance==null){//检查实例,如果不存在就进入同步区块 //注意只有第一次才彻底执行这里的代码。 synchronized(Singleton.class){ if(uniqueInstance==null){ //进入区块再检查一次。如果仍是null,才创建实例。 uniqueInstance = new Singleton(); } } } return uniqueInstance; }}
这样就解决了同步导致性能降低的问题。
最后有一点需要注意:双重加锁不适用于1.4及更早版本的java。
阅读全文
0 0
- 设计模式之 单例设计模式
- 设计模式之 单例设计模式
- 设计模式之单例设计模式
- 设计模式之-----------单例设计模式
- 设计模式之:单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之-单例设计模式
- 设计模式之单例设计模式 标签: 设计模式
- 设计模式之单例
- 设计模式之单例
- 设计模式之 单例
- Spring+SpringMVC+Hibernate三大框架整合
- Linux epoll简单脉络
- 关于嵌入式的系统,原来自己知道的太少了
- C++文件操作——相对路径与绝对路径
- Java项目——简单的WebServer(二)
- 设计模式之单例模式
- SQL(DDL、DML)
- Activity 生命周期
- Deep Learning(深度学习)神经网络如何识别
- 最新Mysql5.7安装教程(图文版本)
- kuangjia
- UVA247[Calling Circles] Floyed求传递闭包 || tarjan求SCC
- BZOJ 1616: [Usaco2008 Mar]Cow Travelling游荡的奶牛
- mac 使用idea切换jdk版本