[code="java"]
import java.math.BigInteger;
import java.util.Arrays;
public class OneValueCache {
private final BigInteger lastNumber;
private final BigInteger[] lastFactors;
// 构造函数
public OneValueCache(BigInteger i, BigInteger[] factors) {
lastNumber = i;
lastFactors = Arrays.copyOf(factors, factors.length);
}
// 没有直接给出保持对象的引用
public BigInteger[] getFactors(BigInteger i) {
if (lastNumber == null || !lastNumber.equals(i))
return null;
else
return Arrays.copyOf(lastFactors, lastFactors.length);
}
}
[/code]
[code="java"]
import java.math.BigInteger;
public class VolatileCachedFactorizer {
private volatile OneValueCache cache = new OneValueCache(null, null);
public void consume(BigInteger i) {
BigInteger[] factors = cache.getFactors(i);
if (factors == null) {
factors = factor(i);
//这个地方初始化cache,是否线程安全?
cache = new OneValueCache(i, factors);
}
System.out.println(factors);
}
private BigInteger[] factor(BigInteger i) {
BigInteger[] factors = { i, i.add(i) };
return factors;
}
}
[/code]
[quote]那构造函数不存在被2个线程同时初始化的情况吗?我就是这里没看懂[/quote]
这和immutable是两个不同的问题:在构造方法没有返回前,没有线程可以调用这个对象,所有构造函数是不需要同步的。
Immutable的就是线程安全的,这就是immutable模式其中一个非常重要的优点。因为在线程中无法对immutable对象的内部状态进行修改,也就不存在并发问题。
对于你的例子,其实BigInteger类本身就是immutable类(这个类的作者是bloch,非常推崇immutable),所以对于OneValueCache类的getFactors方法,你不拷贝直接返回也是没有问题的,当然,都是线程安全的。
immutable的唯一缺点就是可能产生效率问题,在“effect java”里有提到。