在Brian Goetz Concurrency In Practice中,为什么在可伸缩缓存的最后一个例子中有一段时间(真实)?

rus*_*ldb 6 java concurrency multithreading

在Brian Goetz的书"Concurrency In Practice"的代码清单5.19中,他展示了他完成的线程安全的Memoizer类.

我以为我理解了这个例子中的代码,除了我不明白的是什么

while ( true )
Run Code Online (Sandbox Code Playgroud)

是为了开始

public V compute(final A arg) throws InterruptedException
Run Code Online (Sandbox Code Playgroud)

方法.

为什么代码需要while循环?

这是整个代码示例

public class Memoizer<A, V> implements Computable<A, V> {
    private final ConcurrentMap<A, Future<V>> cache
        = new ConcurrentHashMap<A, Future<V>>();
    private final Computable<A, V> c;

    public Memoizer(Computable<A, V> c) { this.c = c; }

    public V compute(final A arg) throws InterruptedException {
        while (true) {
            Future<V> f = cache.get(arg);
            if (f == null) {
                Callable<V> eval = new Callable<V>() {
                    public V call() throws InterruptedException {
                        return c.compute(arg);
                    }
                };
                FutureTask<V> ft = new FutureTask<V>(eval);
                f = cache.putIfAbsent(arg, ft);
                if (f == null) { f = ft; ft.run(); }
            }
            try {
                return f.get();
            } catch (CancellationException e) {
                cache.remove(arg, f);
            } catch (ExecutionException e) {
                throw launderThrowable(e.getCause());
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Bor*_*vić 8

CancellationException上的永久循环重试.如果抛出任何其他异常,则将停止执行.

Biotext dot org 在同一问题上有一篇博客文章.

  • c.compute可能会抛出未经检查的CancellationException.Computable的实现可能更复杂; 例如,使用FutureTask本身; 并合理地抛出CancellationException.从我对Java Lea的Java并发编程的朦胧回忆中,通常应该传播这种异常.Memoizer代码是通用的; 对于给定的例子,这永远不会发生.但是如果你要在另一个上下文中重用Memoizer,处理CancellationException是合理的. (3认同)