Hudi-Lazy学习

134 阅读1分钟

  Hudi 提供了一种懒加载语义实现,Lazy类是一个泛型类,在初始化的时候指定了对应的数据类型。通过 volatile + double check synchnorized使其成为一个线程安全的类。
  Lazy 由三个变量 initializedinitializerref组成。initialized通过volatile修饰,提供了线程安全基础。
  Lazy 提供两个私有的 构造方法,分别通过 eagerlylazily方法调用。
  Lazy 对外提供的方法是 get(),如果是 eagerly则直接放回结果,否则会通过Supplier#get获取结果,再返回,待下次调用的时候,就直接返回,提供了一次性寓意的保障(providing for "exactly once" semantic)。

@ThreadSafe
public class Lazy<T> {

  private volatile boolean initialized;

  private Supplier<T> initializer;
  private T ref;

  private Lazy(Supplier<T> initializer) {
    this.initializer = initializer;
    this.ref = null;
    this.initialized = false;
  }

  private Lazy(T ref) {
    this.initializer = null;
    this.ref = ref;
    this.initialized = true;
  }

  public T get() {
    if (!initialized) {
      synchronized (this) {
        if (!initialized) {
          this.ref = initializer.get();
          this.initializer = null;
          initialized = true;
        }
      }
    }

    return ref;
  }

  /**
   * Executes provided {@code initializer} lazily, while providing for "exactly once" semantic,
   * to instantiate value of type {@link T} being subsequently held by the returned instance of
   * {@link Lazy}
   */
  public static <T> Lazy<T> lazily(Supplier<T> initializer) {
    return new Lazy<>(initializer);
  }

  /**
   * Instantiates {@link Lazy} in an "eagerly" fashion setting it w/ the provided value of
   * type {@link T} directly, bypassing lazy initialization sequence
   */
  public static <T> Lazy<T> eagerly(T ref) {
    return new Lazy<>(ref);
  }
}

使用例子:

# 初始化
# private final Lazy<Schema> schema;
this.schema = schemaOpt.map(Lazy::eagerly)
    .orElseGet(() -> Lazy.lazily(() -> fetchSchema(getSharedHFileReader())));
    
# 使用
public Schema getSchema() {
  return schema.get();
}