一、单例模式: copy
1.静态实例,带有static关键字的属性在每一个类中都是唯一的。
2.限制客户端随意创造实例,即私有化构造方法,此为保证单例的最重要的一步。
3.给一个公共的获取实例的静态方法,注意,是静态的方法,因为这个方法是在我们未获取到实例的时候就要提供给客户端调用的,所以如果是非静态的话,那就变成一个矛盾体了,因为非静态的方法必须要拥有实例才可以调用。
4.判断只有持有的静态实例为null时才调用构造方法创造一个实例,否则就直接返回。
1、普通写法
public class Singleton {
private static Singleton instance; //唯一一个实例
private Singleton() { }
public static Singleton getInstance() {
if(instance==null)
Thread.yield(); //创造多个实例的条件:第一个线程走到这让步,第二个线程走到这,就可能创造多个实例
instance = new Singleton();
return instance;
}
}
但是这种方式有一个问题,为了快速模拟结果,我们加了Thread.yield();
代码:
public class SingletonLearn {
public static void main(String[] args) throws InterruptedException {
final Set<String> instanceSet = Collections.synchronizedSet(new HashSet<String>());
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 10000; i++) {
executorService.execute(new Runnable() {
public void run() {
Singleton singleton = Singleton.getInstance();
instanceSet.add(singleton.toString());
}
});
}
TimeUnit.SECONDS.sleep(10);
System.out.println("------并发情况下我们取到的实例------");
for (String instance : instanceSet) {
System.out.println(instance);
}
executorService.shutdownNow();
}
}
从结果可以看到,创建了多个实例
找了下源码发现用的是这种的
package android.util;
/**
* Singleton helper class for lazily initialization.
*
* Modeled after frameworks/base/include/utils/Singleton.h
*
* @hide
*/
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;
}
}
}
我觉得还是按照源码来吧
2、在Android Studio创建的是这种方式
public class Singleton {
private static Singleton ourInstance = new Singleton();public static Singleton getInstance() { return ourInstance; } private Singleton() { } } 接着抄一句: 上述方式与我们最后一种给出的方式类似,只不过没有经过内部类处理,这种方式最主要的缺点就是一旦我访问了Singleton的任何其他的静态域,就会造成实例的初始化,而事实是可能我们从始至终就没有使用这个实例,造成内存的浪费。
不过在有些时候,直接初始化单例的实例也无伤大雅,对项目几乎没什么影响,比如我们在应用启动时就需要加载的配置文件等,就可以采取这种方式去保证单例。
3、 Android中的使用
在Android开发过程中内存泄漏的问题,所以要更新一种方式,看到资料的意思是,Singleton 是一个单例模式,这个类的生命周期就是application,创建时就持有了activity或其他类的引用,当系统回收时候,发现它仍然在内存中被Instance引用,所以GC回收失败,从而导致内存泄漏
public class WindowMnagerUtil {
private static WindowMnagerUtil mWindowInstance;
private Context context;
private WindowMnagerUtil(Context context) {
this.context = context.getApplicationContext();//这样单利模式的生命周期和应用一样了
}
public static WindowMnagerUtil getWindowInstance(Context context) {
if (mWindowInstance == null)
mWindowInstance = new WindowMnagerUtil(context);
return mWindowInstance;
}
public void createWindow(Context context) {
}
}
reference :
http://blog.youkuaiyun.com/u010687392/article/details/49909477