C++ 实现
- c++ 实现单例,并返回 单例的 shared_ptr 持有:
class Singleton
{
public:
Singleton(Singleton const&) = delete; // 删除拷贝构造函数
Singleton& operator=(Singleton const&) = delete; // 删除赋值
static std::shared_ptr<Singleton> instance()
{
static std::shared_ptr<Singleton> s{new Singleton};
// static std::shared_ptr<Singleton> s{new Singleton,[] (Singleton* p) { delete p; }}; 这种写法会自定义一个析构回掉
return s;
}
std::string getStrVal(){
return "hello singleton";
}
private:
Singleton() {}
};
上面的写法中 是 Single const & ,有一个疑问就是 const Class& and Class const& 这两种写法有区别吗?
答案是没有区别。都表示对一个类的实例的引用
https://stackoverflow.com/questions/35153124/any-difference-between-const-class-and-class-const
Java 实现
- 双重检查锁
这种方式是一种懒汉模式,使用的时候再加载,节约了内存,同时使用volatile 关键字防止了指令重排,(如果不加volatile)可能Singleton的初始化操作和返回操作的指令进行了重排,返回后才进行初始化,这个时候另一个线程如果调用了该对象,就会出问题。
class Singleton{
private volatile static Singleton instance = null;
private Singleton() {
}
public static Singleton getInstance() {
if(instance==null) {
synchronized (Singleton.class) {
if(instance==null)
instance = new Singleton();
}
}
return instance;
} }
- 懒汉式
class Singleton {
private static Singleton sSingleton;
private Singleton() {
}
private static synchronized Singleton getInstance() {
if (sSingleton == null) {
sSingleton = new Singleton();
}
return sSingleton;
}
}
该方式实现了懒加载,但是getInstance()方法需要加synchronized锁,影响效率。
- 饿汉式
class Singleton {
private Singleton() {
}
private static Singleton singleton = new Singleton();
private static Singleton getInstance() {
return singleton;
}
}
该方式使用classloader初始化加载机制避免了多线程初始化对象,但是instance在类加载的时候就会初始化,没有做到懒加载。
- 静态内部类
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
使用Classloader机制保证了初始化instance时只有一个线程,同时只有在使用SingleHolder类的时候才会去主动创建实例,做到了懒加载。
- 使用枚举
class Resource{
}
public enum SomeThing {
INSTANCE;
private Resource instance;
SomeThing() {
instance = new Resource();
}
public Resource getInstance() {
return instance;
}
}
INSTANCE对象会在类加载的时候创建,并且还自动支持序列化机制,防止反序列化重新创建新的对象。
- 抽象类实现单例模式
自己在看android源码的时候看到了一种抽象类实现单例的方式,这里进行记录
源码位置;
android.util.Singleton
/**
* Singleton helper class for lazily initialization.
*/
public abstract class Singleton<T> {
public Singleton() {
}
private T mInstance;
protected abstract T create();
public final T get() {
synchronized (this) {
if (mInstance == null) {
mInstance = create();
}
return mInstance;
}
}
}
上面定义了一个抽象类,抽象类中有抽象方法create,get获取单例的时候会调用抽象方法创建我们需要的单例对象,从而实现了懒加载,自己理解上面的if判断也可以换成双重教研锁,这样能更好点。
使用方式:
class Resource {
static {
System.out.println("resource init");
}
}
private Singleton<Resource> mResource = new Singleton<Resource>() {
@Override
protected Resource create() {
return new Resource();
}
};