我遇到了一些我想理解的悖论。基本上,我在线程设置中有对象的两个变体-变体的不同之处仅在于一个变体具有固定长度的不可变对象数组,而第二个变体比第一个变体慢得多。设置如下:
final class Object {
public Pair<Long, ImmutableThing> cache,
public ImmutableThing getThing(long timestamp) {
if (timestamp > cache.getKey()) {
ImmutableThing newThing = doExpensiveComputation(timestamp);
cache = new Pair(newThing.getLong(), newThing);
return newThing; }
else { return cache.getValue()}
第一个版本显示了getThing方法的更好性能:它查找高速缓存,如果数据有效,则将其返回,否则将进行相当昂贵的计算,更新高速缓存并返回新值。我了解这不是编写时所说的线程安全,但这是第二个变体:
final class SlowerObject {
public Pair<Long, ImmutableThing> cache;
public final ArrayList[ImmutableThing] timelineOfThings;
public ImmutableThing getThing(long timestamp) {
if (timestamp > cache.getKey()) {
ImmutableThing newThing = findInTimelineOfThings(timestamp);
cache = new Pair(newThing.getLong(), newThing);
return newThing; }
else { return cache.getValue()}
在第二个变体中,我们预先计算了一个数组,该数组存储了我们要从getThing返回的事物的所有可能值(在我的情况下,只有4种可能性)。如果高速缓存无效,则无需进行计算,而只是在数组中查找直到找到正确的缓存,然后找出正确的计算几乎是即时的-仅比较长值。该数组永远不会被重写,只需要读取即可。
这都是在线程环境中发生的。为什么第二个要慢一些?