惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

aimingoo的专栏
aimingoo的专栏
雷峰网
雷峰网
博客园 - 叶小钗
V
V2EX
博客园 - Franky
博客园_首页
小众软件
小众软件
Microsoft Security Blog
Microsoft Security Blog
The GitHub Blog
The GitHub Blog
A
About on SuperTechFans
H
Hackread – Cybersecurity News, Data Breaches, AI and More
阮一峰的网络日志
阮一峰的网络日志
WordPress大学
WordPress大学
Blog — PlanetScale
Blog — PlanetScale
J
Java Code Geeks
T
The Blog of Author Tim Ferriss
U
Unit 42
Microsoft Azure Blog
Microsoft Azure Blog
月光博客
月光博客
S
SegmentFault 最新的问题
B
Blog RSS Feed
博客园 - 【当耐特】
D
Docker
N
Netflix TechBlog - Medium

博客园 - JackMa

设计模式 外观 Facade 设计模式 适配器-Adapter 设计模式 命令-Command 积累PDU 设计模式 工厂-Factory 设计模式 策略-Strategy,装饰-Decorator,观察者-Observer Java多线程编程 Red Hat Linux认证 认识Agile,Scrum和DevOps 博客目标 iOS Development Learning 13Nov 重新起步 iOS 开发 XML学习笔记(七)Schema语法杂项 XML学习笔记(六)Schema语法之复杂类型 UML和模式应用-第一部分:绪论 XML学习笔记(五)Schema语法之简单类型 XML学习笔记(四)Schema介绍篇 XML学习笔记(三)进阶篇 Xml学习笔记(二)Javascript篇
设计模式 单件-Singleton
JackMa · 2016-03-31 · via 博客园 - JackMa

单件模式 Singleton

什么时候使用?当需要独一无二的对象时,请想起他。

举例:线程池(threadpool),缓存(cache),对话框,处理偏好设置和注册表(registry)的对象,驱动程序对象。

无需具体例子,先看类图:包含一个private的自己的实例。private的构造函数,确保无法在类以外创建。在getInstance()中检测私有实例是否创建,未则创建,若已存在则直接返回。

看代码更好理解记忆。

经典实现方式 Typical Singleton

public class Singleton {
  private static Singleton uniqueInstance;
  private Singleton() {}
  public static Singleton getInstance {
    if (uniqueInstance == null) {
      uniqueInstance  = new Singleton();
    }        
    return uniqueInstance;
 }            
}

经典实现看似完美,但存在问题。它不是线程安全的。当两个线程同时调用的时候,有可能同时进入 uniqueInstance == null 的if块中。这样对象就不是唯一了。后进入的线程会获得一个新的instance。解决方法,马上直观想到,使用synchronized确保线程安全。 

Singleton Lazy Initialized (延迟加载)

public class Singleton {
  private static Singleton uniqueInstance;
  private Singleton() {}
  public static synchronized Singleton getInstance {
    if (uniqueInstance == null) {
      uniqueInstance  = new Singleton();
    }        
    return uniqueInstance;
 }            
}

如果对性能要求非常高,以上synchronized确实每次都要判断有性能担忧。可以改进如下。

Singleton Eagerly Initialized (急切创建)

public class Singleton {
  private static Singleton uniqueInstance = new Singleton();
  private Singleton() {}
  public static synchronized Singleton getInstance {
    return uniqueInstance;
 }            
}

很好的解决问题了。以上利用了JVM加载机制。在加载类的时候就吧实例创建好。除此,还有一种方法。

Singleton Double-checked Locking (双重检查锁)

public class Singleton {
  private volatile static Singleton uniqueInstance;
  private Singleton() {}
  public static Singleton getInstance {
    if (uniqueInstance == null) {
      synchronized (Singleton.class) {
          if (uniqueInstance == null) {  
             uniqueInstance  = new Singleton();
          }
      }
    }        
    return uniqueInstance;
 }            
}

以上使用了volatile关键字,使uniqueInstance是线程同步读的。即线程总能读到最新的值。uniqueInstance为null时才进行创建。使用synchrinized确保线程安全。同时在块内再次检测是否需要创建。