首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java中的并发缓存

Java中的并发缓存
EN

Stack Overflow用户
提问于 2013-05-10 22:45:35
回答 3查看 1.7K关注 0票数 1

我正在从Brian Goetz的并发书籍中寻找对以下代码的解释。

代码语言:javascript
复制
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());
        }
    }
}

另外,在putIfAbsent()调用之后,为什么语句f = ft;而不是直接做ft.run()呢?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-05-10 23:28:46

如果已经存在,则putIfAbsent的返回值是现有的;如果没有,则返回null,然后将新的返回值放入其中。

代码语言:javascript
复制
        f = cache.putIfAbsent(arg, ft);

        if (f == null) {
            f = ft;
            ft.run();
        }

所以if ( f == null )的意思是“我们把ft放到缓存里了吗?”显然,如果我们将其放入缓存,我们现在需要将f设置为缓存中的值,即ft

如果我们没有将ft放到缓存中,那么f已经是缓存中的值了,因为它是putIfAbsent返回的值。

票数 1
EN

Stack Overflow用户

发布于 2013-05-10 22:49:49

因为您将返回f.get()并可能从缓存中删除f。这允许一段代码适用于所有实例。

代码语言:javascript
复制
    try {
        return f.get();
    } catch (CancellationException e) {
        cache.remove(arg, f);

如果你没有在上面用对ft的引用替换f,那么每次putIfAbsent返回null时,你都会得到一个NPE。

票数 0
EN

Stack Overflow用户

发布于 2013-05-11 00:47:24

代码的思想如下所示。计算某些值的请求来自不同的线程。如果一个线程已经启动了某个值的计算,其他需要相同结果的线程不应该重复计算,而应该等待初始计算。当计算完成时,结果被保存在缓存中。

这种模式的例子是java类的加载。如果一个类正在被加载,而另一个线程也请求加载相同的类,那么它不应该自己加载它,而是等待第一个线程的结果,以便始终只有一个给定类的实例,由相同的类加载器加载。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16484939

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档