3

本文主要介绍如何利用Guava的Suppliers.memoize实现单例。

实例

/**
 * 利用Suppliers.memoize实现单例
 * Created by xixicat on 15/12/25.
 */
public class SuppilerSingletonTest {

    class HeavyObject{
        public HeavyObject() {
            System.out.println("being created");
        }
    }

    class ObjectSuppiler implements Supplier<HeavyObject>{

        @Override
        public HeavyObject get() {
            return new HeavyObject();
        }
    }

    /**
     * 每次都new一次
     */
    @Test
    public void testNotSingleton(){
        Supplier<HeavyObject> notCached = new ObjectSuppiler();
        for(int i=0;i<5;i++){
            notCached.get();
        }
    }

    /**
     * 单例
     */
    @Test
    public void testSingleton(){
        Supplier<HeavyObject> notCached = new ObjectSuppiler();
        Supplier<HeavyObject> cachedSupplier = Suppliers.memoize(notCached);
        for(int i=0;i<5;i++){
            cachedSupplier.get();
        }
    }
}

Suppliers.memoize方法

/**
   * Returns a supplier which caches the instance retrieved during the first
   * call to {@code get()} and returns that value on subsequent calls to
   * {@code get()}. See:
   * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
   *
   * <p>The returned supplier is thread-safe. The supplier's serialized form
   * does not contain the cached value, which will be recalculated when {@code
   * get()} is called on the reserialized instance.
   *
   * <p>If {@code delegate} is an instance created by an earlier call to {@code
   * memoize}, it is returned directly.
   */
  public static <T> Supplier<T> memoize(Supplier<T> delegate) {
    return (delegate instanceof MemoizingSupplier)
        ? delegate
        : new MemoizingSupplier<T>(Preconditions.checkNotNull(delegate));
  }

  @VisibleForTesting
  static class MemoizingSupplier<T> implements Supplier<T>, Serializable {
    final Supplier<T> delegate;
    transient volatile boolean initialized;
    // "value" does not need to be volatile; visibility piggy-backs
    // on volatile read of "initialized".
    transient T value;

    MemoizingSupplier(Supplier<T> delegate) {
      this.delegate = delegate;
    }

    @Override public T get() {
      // A 2-field variant of Double Checked Locking.
      if (!initialized) {
        synchronized (this) {
          if (!initialized) {
            T t = delegate.get();
            value = t;
            initialized = true;
            return t;
          }
        }
      }
      return value;
    }

    @Override public String toString() {
      return "Suppliers.memoize(" + delegate + ")";
    }

    private static final long serialVersionUID = 0;
  }

参考


codecraft
11.9k 声望2k 粉丝

当一个代码的工匠回首往事时,不因虚度年华而悔恨,也不因碌碌无为而羞愧,这样,当他老的时候,可以很自豪告诉世人,我曾经将代码注入生命去打造互联网的浪潮之巅,那是个很疯狂的时代,我在一波波的浪潮上留下...