我发现这篇文章是关于Lazy:C#4.0中的懒惰 - 懒惰
使用Lazy对象获得最佳性能的最佳实践是什么?有人能指出我在实际应用中的实际用途吗?换句话说,我什么时候应该使用它?
有哪些推荐的方法可以实现线程安全的延迟初始化?例如,
// Not thread-safe
public Foo getInstance(){
if(INSTANCE == null){
INSTANCE = new Foo();
}
return INSTANCE;
}
Run Code Online (Sandbox Code Playgroud) 在Java中对静态单例进行延迟初始化时,可以执行以下操作:
public class Bob {
private static class SingletonWrapper {
private static final Bob instance = new Bob();
}
public static Bob getInstance() {
return SingletonWrapper.instance;
}
}
Run Code Online (Sandbox Code Playgroud)
因为内部类SingletonWrapper仅在第一次访问时加载,Bob()所以在getInstance()调用之前不会创建内部类.
我的问题是,是否有任何类似的技巧可用于在非静态上下文中对成员变量进行惰性实例化.
public class Bob {
// Clearly this doesn't work as not lazy
private final InnerWrapper wrapper = new InnerWrapper();
private class InnerWrapper {
private final Jane jane = new Jane();
}
public Jane getJane() {
return wrapper.jane;
}
}
Run Code Online (Sandbox Code Playgroud)
有没有办法我们可以有一个Jane内部的实例Bob和线程安全地只有按需创建实例而不使用双重检查锁定或 …
据我所知,这种方法记忆(缓存)作为参数传递的供应商的价值.据我所知它表现得像单身模式.谁能解释它是如何工作的?
public static <T> Supplier<T> memoize(final Supplier<? extends T> valueSupplier)
{
final List<T> memoryList= new ArrayList<>();
return () -> {
if (memoryList.isEmpty()) {
memoryList.add(valueSupplier.get());
}
return memoryList.get(0);
};
}
Run Code Online (Sandbox Code Playgroud)
用法如下:
Supplier<SomeClass> cachedValue = memoize(() -> someClassObject.getSomeValueToBeCached());
cachedValue.get().doMethod();
Run Code Online (Sandbox Code Playgroud) 我知道AtomicReference有compareAndSet,但我觉得我想做的是这个
private final AtomicReference<Boolean> initialized = new AtomicReference<>( false );
...
atomicRef.compareSetAndDo( false, true, () -> {
// stuff that only happens if false
});
Run Code Online (Sandbox Code Playgroud)
这可能也有效,可能会更好。
atomicRef.compareAndSet( false, () -> {
// stuff that only happens if false
// if I die still false.
return true;
});
Run Code Online (Sandbox Code Playgroud)
我注意到有一些新的功能结构,但我不确定它们中是否有任何一个是我正在寻找的。
任何新的构造都可以做到这一点吗?如果是这样,请提供一个例子。
更新
为了简化我的问题,我试图找到一种不太容易出错的方法来保护代码,以“为对象做一次”或(真的)懒惰的初始化方式,我知道我团队中的一些开发人员compareAndSet感到困惑。
我目前正在用Java创建自己的持久性数组,该数组使用二进制搜索树存储值的集合。
我想添加一个以a Function作为参数的map方法来生成一个新数组。除非请求特定值,否则我不希望评估这些功能。这是很简单的事情,因为lambdas是惰性评估的。但是,我也只希望函数只被评估一次,即使多次请求结果也是如此。
我可以创建一个存储供应商的节点,并在评估时更新结果:
class Node<T> {
private T value;
private Supplier<T> supplier;
public T get() {
if (null != value)
return value;
value = supplier.get();
return value;
}
}
Run Code Online (Sandbox Code Playgroud)
... where supplier是从Function应用于持久化数组旧版本中的值得出的。
但是,这不再是一种功能性方法,并且有可能在多线程系统中引起错误*。在供应商返回空值**的情况下,这也不会产生任何优势。
另一种方法是Node在get调用中返回的实例:
class Node<T> {
private final Optional<T> value;
private final Supplier<T> supplier;
Node(Supplier<T> supplier, T value) {
this.supplier = supplier;
this.value = Optional.ofNullable(value);
}
public Tuple<Node<T>, T> get() {
if (null != value)
return new Tuple<>(this, value.orElse(null));
T result = …Run Code Online (Sandbox Code Playgroud) 我编写了以下代码来Lazy<T>在Java中进行模拟:
import java.util.function.Supplier;
public class Main {
@FunctionalInterface
interface Lazy<T> extends Supplier<T> {
Supplier<T> init();
public default T get() { return init().get(); }
}
static <U> Supplier<U> lazily(Lazy<U> lazy) { return lazy; }
static <T>Supplier<T> value(T value) { return ()->value; }
private static Lazy<Thing> thing = lazily(()->thing=value(new Thing()));
public static void main(String[] args) {
System.out.println("One");
Thing t = thing.get();
System.out.println("Three");
}
static class Thing{ Thing(){System.out.println("Two");}}
}
Run Code Online (Sandbox Code Playgroud)
但我得到以下警告:
"
(T)Main中的值不能应用于(com.company.Main.Thing)原因:没有类型变量T的实例存在,因此Supplier<T>符合Lazy<Thing>"
你能帮我找出问题所在吗?提前致谢!
我正在关注这篇文章https://proandroiddev.com/detecting-when-an-android-app-backgrounds-in-2018-4b5a94977d5c来实现android生命周期,但是在java上具有Application类的遗留应用程序上.
我怎样才能在java中实现这个kotlin代码?
private val lifecycleListener: SampleLifecycleListener by lazy {
SampleLifecycleListener()
}
Run Code Online (Sandbox Code Playgroud)
我觉得这是一个愚蠢的问题,但我不熟悉懒惰的初始化,我不知道如何搜索这个问题,任何"懒惰理论链接"也将受到欢迎.