前言
单例是运行最广泛的设计模式之一。在应用这个模式时,单例模式的类必须保证只有一个实例存在。多用于整个程序只需要有一个实例,通常很消耗资源的类,比如线程池,网络请求,Bitmap创建,访问数据库等。由于类比较耗资源,所以没必要让它构造多个实例,这种就是单例模式比较好的使用场景。
定义
确保某一个类只有一个实例,并且自行实例化,向整个系统提供这个唯一实例。
举例
1.懒汉式(线程安全)
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
- 描述:这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。
- 优点:第一次调用才初始化,避免内存浪费。
- 缺点:效率较低,加锁 synchronized 才能保证单例,但加锁会影响效率。
2.饿汉式
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
- 描述:这种方式比较常用,但容易产生垃圾对象。
- 优点:没有加锁,执行效率很提高。
- 缺点:类加载时就初始化,浪费内存。
3.双重校验锁(DCL)
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
- 描述:这种方式采用双锁机制,安全且在多线程情况下能保持高性能。该方式也是我们较为推荐的方式。
4.静态内部类
public class Singleton{
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton(){}
public static Singleton getSingleton(){
return SingletonHolder.INSTANCE
}
}
描述:这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。
5.Kotlin下的单例模式
class Singleton private constructor() {
companion object {
val instance: Singleton by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { Singleton() }
}
}
class Singleton private constructor() {//这里可以根据实际需求发生改变
companion object {
@Volatile private var instance: Singleton? = null
fun getInstance(property: Int) =
instance ?: synchronized(this) {
instance ?: Singleton().also { instance = it }
}
}
}
网友评论