Hudi 提供了一种懒加载语义实现,Lazy类是一个泛型类,在初始化的时候指定了对应的数据类型。通过 volatile + double check synchnorized使其成为一个线程安全的类。
Lazy 由三个变量 initialized、initializer、ref组成。initialized通过volatile修饰,提供了线程安全基础。
Lazy 提供两个私有的 构造方法,分别通过 eagerly、lazily方法调用。
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();
}