前言
在Java的诸多设计模式中,我们在开发中使用最简单的大概应该是单例模式了。单例模式的实现我们通常用getInstance() 方法,不管在那个类里面调用这个方法,都只能获取到该类的唯一实例,也就是说在不同的地方调用这个方法获取的都是同一个对象。单例模式的构造器通常是私有的
,这样就避免了其他类通过创建构造器的方法创建实例。
实现方式
这里我们只列举两种实现方式,也是在我们开发中经常使用的实现方式,至于像懒汉式、饿汉式、枚举什么的,大概了解下就OK了,实际开发中很少用到。
一、 静态内部类实现单例模式
public class Singleton {
private Singleton() {}
private static class SingletonHolder {
private static Singleton singletonHolder = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.singletonHolder;
}
}
这种方式是我来到新公司后经常接触的一种实现方式,也是我非常建议大家去写的一种方式。他的实现思想就是把Singleton 实例放到一个静态内部类SingletonHolder中,这样就能避免静态实例在Singleton 类开始加载的时候就创建出来引发的资源浪费,并且因为这个静态内部类只会被加载一次,所以在多线程调用getInstance() 方法的时候也能够保证线程安全。
二、DCL(双重校验锁)实现单例模式
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
这里采用的是双重检查+锁的方式,安全且在多线程情况下能保持高性能。这里主要介绍下为什么要检查两次,进入方法过后,先检查实例是否存在,如果不存在才进入下面的同步块,这是第一重检查。进入同步块过后,再次检查实例是否存在,如果不存在,就在同步的情况下创建一个实例,这是第二重检查。这样一来,就只需要同步一次了,从而减少了多次在同步情况下进行判断所浪费的时间。
最后
其实还是要感谢这位作者的这篇文章 Java设计模式之单例模式及线程安全的懒加载实现,对单例模式各种实现讲解的真的很详细,我只不过是简单的介绍了下我们开发工作中最常使用的两种实现方式,想看更多的实现方式可以去看这篇文章。作者最后强烈推荐枚举实现单例模式的方式,这里也补充下:
public enum Singleton {
instance;
public static Singleton getInstance() {
return instance;
}
}
我也很喜欢这种实现方式,它是最简单的单例实现方式。但是我在工作中很少见到这种单例的实现方式,如果日后我经常在工作中遇到的话,我会考虑把DCL的那种实现方式用枚举方式替换掉。