单例模式
2018-11-28 本文已影响0人
幸运星32
1:饿汉模式
public class Singleton{
private static Singleton instance = new Singleton();
private Singleton(){
}
public static Singleton getInstance(){
return instance;
}
}
这种方式在类加载时就完成了初始化,所以类加载会慢一些,但是获取对象的速度块,它是基于类加载机制,避免类多线程的同步问题,但是没有达到懒加载的效果,如果一直没有使用该类,会造成内存浪费。之所以叫做饿汉,是因为它获取对象的速度像饿汉吃饭的速度一样快。
2:懒汉模式(线程不安全)
public class Singleton{
private static Singleton instance;
private Singleton(){
}
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
懒汉模式声明了一个静态对象,在用户第一次调用的时候初始化,节约了资源,但是第一次加载时需要实例化,反应较慢,而且在多线程时不能正常工作,他是线程不安全的模式。之所以叫他懒汉是因为他只有在使用的时候才初始化。
3:懒汉模式(线程安全的)
public class Singleton{
private static Singleton instance;
private Singleton(){
}
public static synchronized Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
这种写法能够在多线程中很好的工作,但是每次调用getInstance方法时都要进行同步,会造成不必要的同步开销,而且大部分时候我们用不到同步,所以不建议用此模式。
4:双重检查模式(DCL)
public class Singleton{
private volatile static Singleton instance;
private Singleton(){
}
public static Singleton getInstance(){
if(instance == null){
synchronized(Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
}
}
这种写法其实是对线程安全的懒汉模式的一种优化,在getinstance方法中对instance进行了两次空判断,第一次是为了不必要的同步,第二次是在instance为空的情况下才创建实例。这里的volatile关键字,是为了满足变量变化时,实时的体现在共享内存中,放在这里可能会影响一些性能,但考虑到程序的正确性,牺牲这点性能是值得的。DCL的优点是资源利用率搞,第一次执行getinstance的时候才实例化对象,效率高。但是在高并发的情况下会出现失效的问题。
5:静态内部类单例模式
public class Singleton{
private Singleton(){
}
public static Singleton getInstance(){
return SingletonHolder.sInstance;
}
private static class SingletonHolder{
private static final Singleton sInstance = new Singleton();
}
}
这种形式在第一次加载Singleton类的时候并不会初始化sInstance,只有在第一次调用getInstance方法时虚拟机加载SingleHolder并初始化sInstance。这样不仅能确保线程安全,也能保证Singleton类的唯一性。所以静态内部类单例模式是比较推荐的模式。
6:枚举单例
public enum Singleton{
INSTANCE;
public void doSomeThing(){
}
}
枚举单例是线程安全的,并且在任何情况下都是单例。但是在Android开发中枚举是不推荐使用的。