什么是单例(Singleton)模式
Singleton指仅仅被实例化一次的类。Singleton通常被用来代表那些本质上唯一的系统组件。
实现单例模式可以带来如下好处:
- 某些类的创建比较频繁,对于一个大型对象,这是一笔很大的开销。
- 省去了new的操作,降低了系统内存的使用频率,减轻GC的压力。
- 有些类是如交易系统引擎,控制着交易流程,如果系统中存在多个将会使系统混乱。
经典单例模式的实现
- 使用一个private的构造器避免直接调用类的构造。
- 使用一个公共的接口来取得单例。
ClassicSingletonTest.java
public class ClassicSingletonTest
{
public static void main(String[] args)
{
Singleton singleton1 = Singleton.getInstance();
Singleton Singleton2 = Singleton.getInstance();
if (singleton1 == singleton1)
{
System.out.println("Equal");
}
}
}
class Singleton
{
public static Singleton instance = null;
private Singleton(){};
public static Singleton getInstance()
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
这个单例模式使用了懒加载(lazy initialization),单例只有在第一次调用getInstance()方法时才会被创建。懒加载确保了单例只会在被需要的时候创建。在上述例子中,我们可以看到Singleton的构造器被设置成了private的,这意味着这个单例模式无法被继承,所以最好的方法应该声明此单例类为final。此外,经典单例模式还存在以下几点值得讨论的地方:
- 当有多不同classloaders来加载这个单例类时,可能会出现多个实例。
- 如果单例类实现了序列化接口,当这个类被解序列化多次的时候可能会出现多个实例。
- 更重要的是,经典单例模式不是线程安全的,当同时有多个线程调用getInstance()方法时,线程A进入了if语句块,然后将CPU时间让给线程B,线程B检测到instance还是null,也进入到了if语句块,这样就会导致两个实例的产生。