1 简介
单例模式涉及到一个单例类,该类负责自己创建自己的唯一对象,且必须提供给其他对象访问其唯一对象的方式。
- 意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点;
- 关键代码:构造函数私有;
- 应用场景:
- 要求生产唯一序列号;
- 创建的一个对象需要消耗的资源过多,比如I/O与数据库的连接等;
- 每台计算机有若干个打印机进程,但只能有一个打印机守护进程,以避免多个打印作业同时输出到打印机;
2 实现(饿汉式)
2.1 步骤一
创建一个 Singleton 类。
SingleObject.java
public class SingleObject {
//创建 SingleObject 的一个对象
private static SingleObject instance = new SingleObject();
//让构造函数为 private,这样该类就不会被实例化
private SingleObject(){}
//获取唯一可用的对象
public static SingleObject getInstance(){
return instance;
}
public void showMessage(){
System.out.println("Hello World!");
}
}
2.2 步骤二
从 singleton 类获取唯一的对象。
SingletonPatternDemo.java
public class SingletonPatternDemo {
public static void main(String[] args) {
//不合法的构造函数
//编译时错误:构造函数 SingleObject() 是不可见的
//SingleObject object = new SingleObject();
//获取唯一可用的对象
SingleObject object = SingleObject.getInstance();
//显示消息
object.showMessage();
}
}
2.3 步骤三
执行程序,输出结果:
Hello World!
3 几种实现方式
3.1 线程不安全的懒汉式
是否懒初始化:是
是否多线程安全:否
实现难度:易
描述:这种方式没有加锁,因此不支持多线程,严格意义上并不算单例模式。
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
3.2 线程安全的懒汉式
是否懒初始化:是
是否多线程安全:是
实现难度:易
描述:这种方式实现了懒初始化(避免内存浪费),且能够在多线程中很好的工作,但每次调用都要加锁,效率很低。
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
3.3 饿汉式
是否懒初始化:否
是否多线程安全:是
实现难度:易
描述:这种方式基于 classloader 机制避免了多线程的同步问题,但类加载时就初始化,没能实现懒初始化,造成内存浪费。
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
3.4 双重校验锁
是否懒初始化:是
是否多线程安全:是
实现难度:较复杂
描述:这种方式采用synchronized+volatile,实现了懒初始化、线程安全且能保持高性能。
public class Singleton {
private volatile static Singleton instance;
private Singleton (){}
public static Singleton getSingleton() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}