单例模式是一种常见的设计模式,它的写法也有好几种,这里主要介绍三种:懒汉式、饿汉式、枚举类实现。
懒汉式单例
基础饿汉式单例
| 12
 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关键字加以优化。
方法同步
| 12
 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;
 }
 
 }
 
 | 
  加入静态方法同步可以实现多线程的情况下只有一个实例被创建。但是同时也会有些问题:只有第一次创建实例时才需要添加类锁,因此之后的方法调用的同步都是一种累赘。可以利用双重检查锁加以改进。
双重检查锁定
| 12
 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;
 }
 }
 
 | 
饿汉式单例
| 12
 3
 4
 5
 6
 7
 8
 
 | public class Singleton {
 private static Singleton singleton = new Singleton();
 private Singleton (){}
 public static Singleton getInstance(){
 return singleton;
 }
 }
 
 | 
  饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的。但由于并不一定是在创建后立即使用甚至可能根本不使用该对象,因此此方式会造成一定的内存浪费。
枚举类单例
| 12
 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版本起,单元素枚举实现单例模式成为最佳的方法