单例模式
前言
最近在整理公司的代码规范,发现部分代码在 SonarSource 中会暴露出单例使用的问题,下面总结一下关于单例的使用问题
注意事项:
避免使用 Double-checked locking
方式:
//错误示范
private static SingletonDemo mInstance;
public static SingletonDemo getInstance() {
if (mInstance == null) {
synchronized (SingletonDemo.class) {
if (mInstance == null) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
mInstance = new SingletonDemo();
}
}
Log.d("ThreadDemo",Thread.currentThread().getName() +" 这里被执行了");
}
return mInstance;
}
上面的代码中,会出现一个问题,在多线程使用此函数时,所以线程会进入第一个if判断,然后因为遇到了synchronized
,就直接越过等待,往下执行了,最后所有线程会等待第一个进入synchronized
代码块的线程处理完后,全部线程才会开始进入synchronized
代码块,所以就出问题了。
正确案例
方式1
使用静态内部类型进行静态实例化
private static class Singleton{
static SingletonDemo singtonDemo = new SingletonDemo();
}
public static SingletonDemo getInstance() {
return Singleton.singtonDemo;
}
方式2
使用同步函数
private static SingletonDemo mInstance;
public static synchronized SingletonDemo getInstance() {
if (mInstance == null) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
mInstance = new SingletonDemo();
Log.d("ThreadDemo", Thread.currentThread().getName() + " 这里被执行了");
}
return mInstance;
}