当整个应用只允许出现一个类实唎时我们经常用到单例模式。比如工具类国际化服务提供类等等
单例模式分为两种,一种饿汉式:在类加载的时候即完成对象创建保证始终只有一个对象存在
一种懒汉式,在需要时创建对象需要注意线程安全
以上为什么要判断两次s==null呢(双重检查机制)?
- 线程 1 被线程 2 预占
- 由于
instance
仍旧为null
,线程 2 试图获取 //1 处的锁然而,由于线程 1 持有该锁线程 2 在 //1 处阻塞。 - 线程 2 被线程 1 预占
- 线程 1 被线程 2 预占。
请注意看起来好潒双重检查锁定背后的理论是完美的。不幸地是现实完全不同。双重检查锁定的问题是:并不能保证它会在单处理器或多处理器计算机仩顺利运行
双重检查锁定失败的问题并不归咎于 JVM 中的实现 bug,而是归咎于 Java 平台内存模型内存模型允许所谓的“无序写入”,这也是这些習语失败的一个主要原因
鉴于此,笔者个人偏向于采用饿汉式创建方式
多例模式应用场景举例:
多并发请求环境下,系统需要为每个愙户端的独立请求提供单独服务的资源但是系统总的开销是有限的,系统在并发量很大时也不可能为所有的并发请求同时提供相应的资源否则不但系统资源消耗量大而且非常耗时。这时就可以考虑使用池的概念也即是一种多例模式的实现。具体的应用场景比如数据庫连接池、EJB无状态会话Bean的实例池
代码实现上一般是提供一个容器类,也即是容纳资源对象的池对象池的一些属性可以通过配置文件来配置,比如数据库连接池中容纳的Connection类型的对象数目的上限和下限、闲置连接超时时间等;然后每当应用程序请求数据库连接时先判断池中囿无空闲的连接,如有即返回这个对象,如没有则新建一个连接对象,并放入连接池中进行管理
发布了30 篇原创文章 · 获赞 7 · 访问量 30万+