Singleton模式是设计模式里最简单的了,但在使用时,还是要注意些细节,可能你在用时也会碰到。废话不多说,请接着看:
1 Introduction
先看定义:
The Singleton Pattern ensures a class has only one instance, and provides aglobal point of access to it.
从定义可以看出,Singleton主要实现两点功能:
1) 只有一个实例
2) 提供全局的入口
2 Implementation
一般是这样写的:
方法1:
public class Singleton {
private static Singleton mInstance; // Static variable to hold one instance
// Constructor is declared private to avoid instantiated by others
private Singleton() {}
public static Singleton getInstance() {
if (null == mInstance)
{
mInstance = new Singleton();
}
return mInstance;
}
}
恩,这样写在面试时一般都能通过。但这里会有问题,特别是在多线程时。
3 Problem
在多线程中,假设有两个线程Thread1, Thread2,都调用Singleton.getInstance(),有可能创建两个instance. 见下图(从Head First Design Pattern上抄的):
4. Improvement
在多线程中,为了同步,一般用synchronized关键字,但具体放的位置还有关系:下面列了3种solution:
方法2: 在getInstance()前加synchronized,
public class Singleton {
private static Singleton mInstance; // Static variable to hold one instance
// Constructor is declared private to avoid instantiated by others
private Singleton() {}
public static synchronized Singleton getInstance() {
if (null == mInstance)
{
mInstance = new Singleton();
}
return mInstance;
}
}
缺点:在每次调用getInstance()时都会阻塞在这里,这样性能会下降。实际上只要在第一次new Singleton时synchronized就可以了,其他时间没必要synchronized。
方法3: 更严谨的方法
public class Singleton {
private static Singleton mInstance; // Static variable to hold one instance
// Constructor is declared private to avoid instantiated by others
private Singleton() {}
public static Singleton getInstance() {
if (null == mInstance)
{
synchronized(Singleton.class)
{
if (null == mInstance)
{
mInstance = new Singleton();
}
}
}
return mInstance;
}
}
这样写的好处是,只在第一次会synchronized,并且不会产生两个instance。推荐这种写法。
当然也有不用写synchronized的方法,前提是你的程序肯定会调用该Singleton类:
方法4
public class Singleton {
private static Singleton mInstance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return mInstance;
}
}
5. Summary
总结下:以前我经常用方法1,觉得也没什么不妥。但从更严谨的角度来说,还是用 方法3最好。
欢迎讨论~~~