一、介绍
单例模式,也叫单子模式,是一种常用的软件设计模式,属于创建型模式的一种。在应用这个模式时,单例对象的类必须保证只有一个实例存在。
单例模式保证了系统只存在一个实例,节省内存资源。减少了重复创建,提高了性能。
二、分类
- 饿汉模式:指全局的单例实例在类装载时构建
- 懒汉模式:指全局的单例实例在第一次被使用时构建。
三、实现方式
- 私有化构造函数
- 提供静态获取单例方法
四、代码实现
1、饿汉模式:
public class App {
public static volatile App instance = new App();
private App(){}
public static App getInstance() {
return instance;
}}
2、懒汉模式:
public class App {private App() {
}
public static volatile App instance;
public static synchronized App getInstance() {
if (instance == null) {
synchronized (App.class) {
if (instance == null) {
instance = new App();
}
}
}
return instance;
}
}
五、懒汉模式的演进
1、判空检验
这种在多线程情况下,容易产生多个实例
public class App {public static App instance ;
public static App getInstance(){
if(instance == null){
instance = new App();
}
return instance;
}
}
2、方法加锁
这种方式,锁力度较大,性能开销大
public class App {
public static App instance;
private App(){
}
public static synchronized App getInstance() {
if (instance == null) {
instance = new App();
}
return instance;
}}
3、双重检验锁
这种方式在多线程情况下也能保证高性能,但是由于JVM创建对象过程不是原子操作,存在指令重排,容易产生报错。
public class App {
private App() {
}
public static App instance;
public static synchronized App getInstance() {
if (instance == null) {
synchronized (App.class) {
if (instance == null) {
instance = new App();
}
}
}
return instance;
}
}
4、双重检验锁+ volatile
即保证多线程高性能,也可以避免指令重排
public class App {
private App() {
}
public static volatile App instance;
public static synchronized App getInstance() {
if (instance == null) {
synchronized (App.class) {
if (instance == null) {
instance = new App();
}
}
}
return instance;
}
}
六、Android源码中的单例模式
InputMethodManager.java
public final class InputMethodManager {
static InputMethodManager sInstance;
public static InputMethodManager getInstance() { synchronized (InputMethodManager.class) {
if (sInstance == null) {
try {
sInstance = new InputMethodManager(Looper.getMainLooper());
} catch (ServiceNotFoundException e) {
throw new IllegalStateException(e);
}
}
return sInstance;
}
}
}
android.util.Singleton.java
public abstract class Singleton<T> {
private T mInstance;
protected abstract T create();
public final T get() {
synchronized (this) {
if (mInstance == null) {
mInstance = create();
}
return mInstance;
}
}
}