一,单例概念
单例模式是一种对象创建模式,它用于产生对象的具体实例,并且确保在系统中这个类只能产生一个实例。
-
好处
(1)对于频繁使用的对象,可以省略创建对象花费的时间,对于一些重量级的对象,是一笔可观的系统开销
(2)由于new的操作减少,对系统内存的使用频率也会减少,减少GC压力,压缩GC停顿时间。
二,单例的写法
- 饿汉模式
public class EagerSingleton {
private static EagerSingleton eagerSingleton = new EagerSingleton();
private EagerSingleton() {
}
public static EagerSingleton getEagerSingleton() {
return eagerSingleton;
}
}
优点:类装载的时候就完成类实例化,避免了线程同步问题
缺点:没实现延迟加载,如果不使用这个类会造成内存浪费
- 懒汉模式(对于饿汉模式的没有懒加载的方式的一种优化)- 不建议使用
public class LazyModeSingleton {
private static LazyModeSingleton lazyModeSingleton;
private LazyModeSingleton() {
}
public static LazyModeSingleton getInstance() {
if (lazyModeSingleton == null) {
lazyModeSingleton = new LazyModeSingleton();
}
return lazyModeSingleton;
}
}
缺点:线程非安全
- 懒汉线程安全
public class LazyModeSingletonSafe {
private static LazyModeSingletonSafe lazyModeSingletonSafe;
private LazyModeSingletonSafe() {
}
public static synchronized LazyModeSingletonSafe getInstance() {
if (lazyModeSingletonSafe == null) {
lazyModeSingletonSafe = new LazyModeSingletonSafe();
}
return lazyModeSingletonSafe;
}
// public static LazyModeSingletonSafe getInstance() {
// synchronized (LazyModeSingleton.class) {
// if (lazyModeSingletonSafe == null) {
// lazyModeSingletonSafe = new LazyModeSingletonSafe();
// }
// }
// return lazyModeSingletonSafe;
// }
}
优点:线程安全
缺点:性能差
- DCL(双重检查锁机制)
public class DCLSingleton {
private static volatile DCLSingleton dclSingleton;//禁止指令jvm重排序
private DCLSingleton() {
}
private DCLSingleton getInstance() {
if (dclSingleton == null) {
synchronized (DCLSingleton.class) {
if (dclSingleton == null) {
//JVM的及时编译器中存在指令重排序优化会导致线程不安全,解决办法 关键字valatile
dclSingleton = new DCLSingleton();}
}
}
return dclSingleton;
}
}
- 静态内部类(建议使用)
public class StaticInneClassesSingleton {
private StaticInneClassesSingleton() {
}
public static StaticInneClassesSingleton getInstance() {
return StaticInneClassesSingletonHolder.staticInneClassesSingleton;
}
private static class StaticInneClassesSingletonHolder {
private final static StaticInneClassesSingleton staticInneClassesSingleton = new StaticInneClassesSingleton();
}
}
优点:具有延迟加载,线程安全,性能优越
原因:使用了static final关键字
- 枚举
public class EnumSingleton {
INSTANCE;
public void doSomeTing(){
}
}
借助JDK1.5中添加的枚举来实现单例模式。不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。
总结:
饿汉模式:无法实现延迟加载
懒汉模式:非线程安全
懒汉模式(线程安全):使用synchronized导致性能缺陷
DCL:JVM及时编译器指令的重排序问题,通过关键字volatile 可以解决,但是也具有一定性能问题
静态内部类/枚举:延迟加载,线程安全,性能好建议使用
三,android中的单例
- Application
public class MyApplication extends Application {
private static MyApplication myApplication;
public static MyApplication getIntstance() {
return myApplication;
}
@Override
public void onCreate() {
super.onCreate();
myApplication = this;
}
}
-
单例模式引起的内存泄漏
如果一个对象已经不需要使用了,而单例对象还持有该对象的引用,那么这个对象将不能被正常回收,这就导致了内存泄漏。
public class Singletonleak {
private static Context mContext;
public static Singletonleak getInstance(Context context) {
// mContext=context;//错误写法
mContext = context.getApplicationContext();//正确写法
return SingletonLeakHolder.singletonleak;
}
private static class SingletonLeakHolder {
private static final Singletonleak singletonleak = new Singletonleak();
}
public void show() {
Toast.makeText(mContext, "zjy", Toast.LENGTH_SHORT).show();
}
}
网友评论