单例模式,多例模式及其应用
2015-05-26 15:16
211 查看
单例模式:
当整个应用只允许出现一个类实例时,我们经常用到单例模式。比如工具类,国际化服务提供类等等
单例模式分为两种,一种饿汉式:在类加载的时候即完成对象创建,保证始终只有一个对象存在
[java] view
plaincopy
Class Singleton{
private static Singleton s = new Singleton ();
private Singleton(){}
public static Singleton getInstance(){
return s;
}
}
一种懒汉式,在需要时创建对象,需要注意线程安全
[java] view
plaincopy
Class Singleton{
private static Singleton s;
private Singleton(){
}
public static Singleton getInstance(){
if(s==null){
synchronized(Singleton.class){//1
if(s==null){ //2
s = new Singleton(); //3
}
}
}
return s;
}
}
以上为什么要判断两次s==null呢(双重检查机制)?
线程 1 进入
由于
线程 1 被线程 2 预占。
线程 2 进入
由于
线程 2 被线程 1 预占。
线程 1 执行,由于在 //2 处实例仍旧为
线程 1 退出
线程 1 被线程 2 预占。
线程 2 获取 //1 处的锁并检查
由于
请注意,看起来好像双重检查锁定背后的理论是完美的。不幸地是,现实完全不同。双重检查锁定的问题是:并不能保证它会在单处理器或多处理器计算机上顺利运行。
双重检查锁定失败的问题并不归咎于 JVM 中的实现 bug,而是归咎于 Java 平台内存模型。内存模型允许所谓的“无序写入”,这也是这些习语失败的一个主要原因。
鉴于此,笔者个人偏向于采用饿汉式创建方式。
多例模式:
多例模式应用场景举例:
多并发请求环境下,系统需要为每个客户端的独立请求提供单独服务的资源,但是系统总的开销是有限的,系统在并发量很大时也不可能为所有的并发请求同时提供相应的资源,否则不但系统资源消耗量大而且非常耗时。这时就可以考虑使用池的概念,也即是一种多例模式的实现。具体的应用场景,比如数据库连接池、EJB无状态会话Bean的实例池
代码实现上一般是提供一个容器类,也即是容纳资源对象的池,对象池的一些属性可以通过配置文件来配置,比如数据库连接池中容纳的Connection类型的对象数目的上限和下限、闲置连接超时时间等;然后每当应用程序请求数据库连接时,先判断池中有无空闲的连接,如有,即返回这个对象,如没有,则新建一个连接对象,并放入连接池中进行管理
当整个应用只允许出现一个类实例时,我们经常用到单例模式。比如工具类,国际化服务提供类等等
单例模式分为两种,一种饿汉式:在类加载的时候即完成对象创建,保证始终只有一个对象存在
[java] view
plaincopy
Class Singleton{
private static Singleton s = new Singleton ();
private Singleton(){}
public static Singleton getInstance(){
return s;
}
}
一种懒汉式,在需要时创建对象,需要注意线程安全
[java] view
plaincopy
Class Singleton{
private static Singleton s;
private Singleton(){
}
public static Singleton getInstance(){
if(s==null){
synchronized(Singleton.class){//1
if(s==null){ //2
s = new Singleton(); //3
}
}
}
return s;
}
}
以上为什么要判断两次s==null呢(双重检查机制)?
线程 1 进入
getInstance()方法。
由于
instance为
null,线程 1 在 //1 处进入
synchronized块。
线程 1 被线程 2 预占。
线程 2 进入
getInstance()方法。
由于
instance仍旧为
null,线程 2 试图获取 //1 处的锁。然而,由于线程 1 持有该锁,线程 2 在 //1 处阻塞。
线程 2 被线程 1 预占。
线程 1 执行,由于在 //2 处实例仍旧为
null,线程 1 还创建一个
Singleton对象并将其引用赋值给
instance。
线程 1 退出
synchronized块并从
getInstance()方法返回实例。
线程 1 被线程 2 预占。
线程 2 获取 //1 处的锁并检查
instance是否为
null。
由于
instance是非
null的,并没有创建第二个
Singleton对象,由线程 1 创建的对象被返回。
请注意,看起来好像双重检查锁定背后的理论是完美的。不幸地是,现实完全不同。双重检查锁定的问题是:并不能保证它会在单处理器或多处理器计算机上顺利运行。
双重检查锁定失败的问题并不归咎于 JVM 中的实现 bug,而是归咎于 Java 平台内存模型。内存模型允许所谓的“无序写入”,这也是这些习语失败的一个主要原因。
鉴于此,笔者个人偏向于采用饿汉式创建方式。
多例模式:
多例模式应用场景举例:
多并发请求环境下,系统需要为每个客户端的独立请求提供单独服务的资源,但是系统总的开销是有限的,系统在并发量很大时也不可能为所有的并发请求同时提供相应的资源,否则不但系统资源消耗量大而且非常耗时。这时就可以考虑使用池的概念,也即是一种多例模式的实现。具体的应用场景,比如数据库连接池、EJB无状态会话Bean的实例池
代码实现上一般是提供一个容器类,也即是容纳资源对象的池,对象池的一些属性可以通过配置文件来配置,比如数据库连接池中容纳的Connection类型的对象数目的上限和下限、闲置连接超时时间等;然后每当应用程序请求数据库连接时,先判断池中有无空闲的连接,如有,即返回这个对象,如没有,则新建一个连接对象,并放入连接池中进行管理
相关文章推荐
- STM32学习笔记(五) ------ I/O的几种工作模式及其应用场合
- PHP中的设计模式及其实际应用浅析
- 云计算总体架构及其应用与商业模式探讨
- VC++与MATLAB混合编程及其应用 通过引擎(Engine),采用客户机服务器的计算模式
- 多线程中的Future模式及其在高性能IO框架netty中的应用
- 单例模式及其在iOS中的应用
- 看似巧合实本然——试论Web2.0与电子商务2.0相结合模式及其应用
- Activity的四种启动模式及其应用场景
- UIViewController的几种跳转模式及其应用
- 彻头彻尾理解单例模式及其在多线程环境中的应用
- Java - 解释一下网络应用的模式及其特点。
- Dirty Flag 模式及其应用
- Android之A面试题①Activity的四种启动模式及其应用场景
- 设计模式之单例模式及其应用
- 23种设计模式及其应用场景
- Dirty Flag 模式及其应用
- Dirty Flag 模式及其应用
- Dirty Flag 模式及其应用
- P2P研究:主要应用模式及其现存问题概要
- 经验模式分解理论及其应用