单例模式的潜在问题与解决方案

单例模式

前言

最近在整理公司的代码规范,发现部分代码在 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;
}
原文地址:https://www.cnblogs.com/cavalier-/p/12744820.html