gpt4 book ai didi

java - 在不影响访问缓存的延迟的情况下刷新缓存

转载 作者:行者123 更新时间:2023-12-03 12:59:09 25 4
gpt4 key购买 nike

我有一个缓存刷新逻辑,并希望确保它是线程安全的并且是正确的方法。

public class Test {

Set<Integer> cache = Sets.newConcurrentHashSet();

public boolean contain(int num) {
return cache.contains(num);
}

public void refresh() {
cache.clear();
cache.addAll(getNums());
}
}

所以我有一个后台线程刷新缓存 - 定期调用 refresh .并且多个线程正在调用 contain同时。我试图避免 synchronized在方法签名中,因为 refresh可能需要一些时间(想象一下 getNum 进行网络调用并解析大量数据)然后是 contain会被阻止。

我认为这段代码不够好,因为如果 contain中间调用 clearaddAll然后 contain总是返回假。

在不影响显着延迟的情况下实现缓存刷新的最佳方法是什么 contain称呼?

最佳答案

最好的方法是使用函数式编程范式,其中您具有不可变状态(在本例中为 Set ),而不是向该集合添加和删除元素,而是创建一个全新的 Set每次要添加或删除元素时。这是在 Java9 中。

然而,为遗留代码实现这种方法可能有点尴尬或不可行。因此,您可以做的是拥有 2 Sets 1 上有 get 方法,它是可变的,然后在 refresh 中分配了一个新实例方法。

public class Test {

volatile Set<Integer> cache = new HashSet<>();

public boolean contain(int num) {
return cache.contains(num);
}

public void refresh() {
Set<Integer> privateCache = new HashSet<>();
privateCache.addAll(getNums());
cache = privateCache;
}
}

编辑 我们不想要或不需要 ConcurrentHashSet ,也就是说,如果您想同时向集合中添加和删除元素,在我看来,这是一件非常无用的事情。但是要换旧的 Set使用一个新的,这就是为什么你只需要一个 volatile 变量来确保你不能同时读取和编辑缓存。

但是正如我在开始时的回答中提到的那样,如果您从不修改集合,而是在每次想要更新集合时创建新集合(请注意,这是一个非常便宜的操作,因为在内部旧集合在操作中重用)。这样您就无需担心并发性,因为线程之间没有共享状态。

关于java - 在不影响访问缓存的延迟的情况下刷新缓存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49020831/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com