美文网首页
Java实际项目使用的Singleton是什么样的

Java实际项目使用的Singleton是什么样的

作者: x_ae1f | 来源:发表于2019-05-19 11:10 被阅读0次

    java面试经常问的一个问题就是单例怎么实现,这个问题主要考察的就是延迟加载和java的内存机制,按照通常的标准答案是这样的:

    class Singleton {
      private static volatile Singleton value;
      private Singleton() {}
      public static Singleton get() {
        if (value == null) {
          synchronized(Singleton.class) {
            if (value == null) {
              value = new Singleton();
            }
            return value;
          }
        }
      }
    }
    

    这个方法理论上是没问题的,但是实际使用中,是有问题的。

    首先,一个singleton就要写一个类,对于大一点的项目,有可能有多个使用单例的场景,岂不是每个都要写一个Singleton类,这就麻烦了。
    其次,可以看到这个单例的构造函数是private,但是平时写的类,几乎不可能只有一个private的构造函数。
    总之,这种写法不太实用,主要还是在面试时考察面试者对Java的基础是否了解。

    实际的单例是怎么样的,可以参考spring的源码

    public class SingletonSupplier<T> implements Supplier<T> {
    
        @Nullable
        private final Supplier<? extends T> instanceSupplier;
    
        @Nullable
        private final Supplier<? extends T> defaultSupplier;
    
        @Nullable
        private volatile T singletonInstance;
    
      @Override
        @Nullable
        public T get() {
            T instance = this.singletonInstance;
            if (instance == null) {
                synchronized (this) {
                    instance = this.singletonInstance; 
                    if (instance == null) {
                        if (this.instanceSupplier != null) {
                            instance = this.instanceSupplier.get();
                        }
                        if (instance == null && this.defaultSupplier != null) {
                            instance = this.defaultSupplier.get();
                        }
                        this.singletonInstance = instance;
                    }
                }
            }
            return instance;
        }
    }
    

    可以看到,实际情况下,Spring并没有每个需要单例的地方都写一个单例,而是提供一个supplier来创建单例。

    这里还有一个小技巧,因为this.singletonInstance已经被volatile修饰,读this.singletonInstance是从主内存读取,这里赋值给instance,只用读一次,速度更快。

    当然,如果要确保严格的单例,那么还要确保SingletonSupplier的对象也是单例的,但是从Spring代码看,并没有这么严格,只要求每个对象的singletonSupplier.get()返回的是单例。

    相关文章

      网友评论

          本文标题:Java实际项目使用的Singleton是什么样的

          本文链接:https://www.haomeiwen.com/subject/nrvfzqtx.html