翻译自
目的
确保一个类只有一个实例,并且提供一个全局访问点。
说明
例子
只有一个象牙塔可以让巫师学习他们的魔法。巫师总是使用同样的魔法象牙塔。这个象牙塔就是单例。
简单的说
确保只创建一个特定类的一个对象。
维基百科
在软件工程中,单例模式是一种软件设计模式,它将一个类的实例化限制为一个对象。对于需要确切的一个对象来协调系统中的操作时是非常有用的。
代码示例
实现单例的最好方式就是单个元素的枚举类
public enum EnumIvoryTower { INSTANCE;}EnumIvoryTower enumIvoryTower1 = EnumIvoryTower.INSTANCE;EnumIvoryTower enumIvoryTower2 = EnumIvoryTower.INSTANCE;assertEquals(enumIvoryTower1, enumIvoryTower2); // true复制代码
恶汉式单例模式
public final class IvoryTower { /** * 私有构造器,所以外部无法实例化该类 */ private IvoryTower() {} /** * 静态实例.类加载完之后被实例 */ private static final IvoryTower INSTANCE = new IvoryTower(); /** * 调用此方法获取单例. * * @return 单例. */ public static IvoryTower getInstance() { return INSTANCE; }}复制代码
懒汉式单例
在Java中Initialize-on-demand-holder idiom 创建懒加载单例是一种安全的方式。当getInstance()调用时,内部类还没有被加载。而类加载是安全的,因此,这种解决方案是线程安全的,尽管没有使用volatile或者synchronized。
public final class InitializingOnDemandHolderIdiom { /** * 私有构造器. */ private InitializingOnDemandHolderIdiom() {} /** * @return 单例 */ public static InitializingOnDemandHolderIdiom getInstance() { return HelperHolder.INSTANCE; } /** * 提供懒加载单例 */ private static class HelperHolder { private static final InitializingOnDemandHolderIdiom INSTANCE = new InitializingOnDemandHolderIdiom(); }}复制代码
线程安全懒汉单例
实例被懒加载,因此需要同步机制。
public final class ThreadSafeLazyLoadedIvoryTower { private static ThreadSafeLazyLoadedIvoryTower instance; private ThreadSafeLazyLoadedIvoryTower() { //防止被反射 if (instance == null) { instance = this; } else { throw new IllegalStateException("Already initialized."); } } /** * 当第一次调用时实例才会被创建,但是由于每次调用都有锁,性能不好 */ public static synchronized ThreadSafeLazyLoadedIvoryTower getInstance() { if (instance == null) { instance = new ThreadSafeLazyLoadedIvoryTower(); } return instance; }}复制代码
线程安全双重检查单例
public final class ThreadSafeDoubleCheckLocking { //内存可见,防止重排 private static volatile ThreadSafeDoubleCheckLocking instance; /** * 私有构造防止被外部实例化 */ private ThreadSafeDoubleCheckLocking() { // 防止被反射 if (instance != null) { throw new IllegalStateException("Already initialized."); } } /** * 公共访问 * * @return 实例 */ public static ThreadSafeDoubleCheckLocking getInstance() { ThreadSafeDoubleCheckLocking result = instance; // 检查是否被实例化,如果已经实例化则返回实例 if (result == null) { // 有可能在其它线程初始化了 // 所以为了确保我们需要锁定一个对象来实现互斥。 synchronized (ThreadSafeDoubleCheckLocking.class) { // 再次将实例赋值给局部变量以检查它是否被其他线程初始化 // 而当前线程被阻止进入锁定区域. 如果它已被初始化,那么我们可以返回之前创建的实例,就像之前的空检查一样。 result = instance; if (result == null) { //实例还是没有被创建(其它线程无法进入),所以我们可以安全地创建实例并且赋值给instance和result。 instance = result = new ThreadSafeDoubleCheckLocking(); } } } return result; }}复制代码
典型用例
- the logging class
- managing a connection to a database
- file manager