单例模式仅有一个实例,自行实例化并提供一个访问它的全局公有静态方法。
注意:单例模式需要注意场景的使用,项目中过多使用单例无益处。
单例的使用情况
一般有两种情况下会应用到单例模式:
- 一:
产生的对象会消耗过多的资源,为避免频繁地创建与销毁对象对资源的浪费。- 数据库操作
- 网络请求
- 线程池(threadpool)
- IO访问操作
- 任务调度器
- 二:
应用系统中只能有一个实例存在,过多的实例会导致应用系统的不稳定。- 操作系统注册表
- android InputMethodManager
- android BluetoothOppManager
单例优缺点
- 优:
可以减少系统内存开支,减少系统性能开销,避免对资源的多重占用、同时操作。 - 缺:
扩展很困难,容易引发内存泄露,测试困难,一定程度上违背了单一职责原则,进程被杀时可能有状态不一致问题。应用退出需要注意单例释放。
推荐一 双重检查锁定Double Check Lock(DCL)方式:
此方法的“Double-Check”体现在进行了两次if (singleton == null)的检查,这样既同步代码块保证了线程安全,同时实例化的代码也只会执行一次,实例化后同步操作不会再被执行,从而高并发下效率提升很多。
注意: JDK 普遍都已超过 1.4,只要在定义单例时加上 1.5 及以上版本具体化了的 volatile关键字,即可保证执行的顺序,从而使单例起效。
//1.4及以下版本定义
private static volatile Singleton mInstance;
//1.5以上版本定义
public final class Singleton {
private static Singleton mInstance;
private Singleton() {
}
public static Singleton getInstance() {
if (mInstance == null) {
synchronized (Singleton.class) {
if (mInstance == null) {
mInstance = new Singleton();
}
}
}
return mInstance;
}
}
推荐二 《Java并发编程实践》极为推崇静态内部类方式:
利用了 classloder 的机制来保证初始化 instance 时只会有一个。这种方式的 Singleton 类被装载时,只要 SingletonHolder 类还没有被主动使用,instance 就不会被初始化。只有在显式调用getInstance()方法时,才会装载 SingletonHolder 类,从而实例化对象。
public final class Singleton {
private Singleton() {
}
public static final Singleton getInstance(){
return SingletonHolder.INSTANCE;
}
private static class SingletonHolder{
private static final Singleton INSTANCE = new Singleton();
}
}
网友评论