单例模式是一种常见的设计模式,它的写法也有好几种,这里主要介绍三种:懒汉式、饿汉式、枚举类实现。
懒汉式单例
基础饿汉式单例
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class Singleton {
private static Singleton singleton;
private Singleton (){}
public static Singleton getInstance(){ if (singleton == null) { singleton = new Singleton(); } return singleton; } }
|
  Singlon
将构造函数设置为私有,使得外部能够获取的唯一Singlon
实例只能通过getInstance
方法创建。
  但是以上饿汉式单例并没有考虑多线程的情况,在多线程时任会产生多个实例。可以添加synchornized
关键字加以优化。
方法同步
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class Singleton {
private static Singleton singleton;
private Singleton (){}
public synchronized static Singleton getInstance(){ if (singleton == null) { singleton = new Singleton(); }
return singleton; }
}
|
  加入静态方法同步可以实现多线程的情况下只有一个实例被创建。但是同时也会有些问题:只有第一次创建实例时才需要添加类锁,因此之后的方法调用的同步都是一种累赘。可以利用双重检查锁加以改进。
双重检查锁定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getInstance(){ if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }
|
饿汉式单例
1 2 3 4 5 6 7 8
| public class Singleton { private static Singleton singleton = new Singleton(); private Singleton (){} public static Singleton getInstance(){ return singleton; } }
|
  饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的。但由于并不一定是在创建后立即使用甚至可能根本不使用该对象,因此此方式会造成一定的内存浪费。
枚举类单例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class Singleton {
private Singleton(){};
public static Singleton getInstance() { return SomeThing.INSTANCE.getInstance(); }
private enum SomeThing { INSTANCE; private Singleton instance; SomeThing() { instance = new Singleton(); } public Singleton getInstance() { return instance; } } }
|
从Java 1.5版本起,单元素枚举实现单例模式成为最佳的方法