gpt4 book ai didi

java - 有条件地计算 ConcurentHashMap 中的值并每隔一定时间替换它

转载 作者:太空宇宙 更新时间:2023-11-04 11:24:39 25 4
gpt4 key购买 nike

在我的应用程序中有一个共享缓存服务。它由多个线程访问,因此它必须是线程安全的。我已经使用 HashMap 实现了它,因为我同步了 getOrCreateToken() 方法,但我也使用 ConcurentHashMap 进行了实现。我的问题是,如果没有必要,我不想执行 service.authenticateWithoutCache() (这是 API 限制,我有义务仅在实际需要时才发出请求)。但是,如果多个线程通过标记 !!!MARKER!!!,则会发出几个新的 NEEDLES token 。 computeIfAbsent 将不起作用,因为应该在某些时间间隔重新发出 token 。我想找到一种方法,仅在满足条件时替换旧票一次,而不是每次多个线程进入 if 语句时替换旧票?

注意:在使用同步 HashMap 实现时,这一点很容易实现,因为同步块(synchronized block)保证只有一个线程正在执行该 block 。

    private static Map<String, TokenResponse> cachedKeys = new ConcurrentHashMap<>();

public static TokenResponse getOrCreateToken(OAuthService service)
throws IOException {

String accessTokenKey = constructAccessTokenKey(configuration);
TokenResponse token = cachedKeys.get(accessTokenKey);
if (token == null) {
TokenResponse alreadyThereToken = cachedKeys.computeIfAbsent(accessTokenKey,
key -> service.authenticateWithoutCache());
return alreadyThereToken;
} else {
Instant now = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant();
Instant createdAt = token.getCreatedAt().atZone(ZoneId.systemDefault()).toInstant();

long minutes = accessTokenExpiredMinutes(createdAt, now);
//!!!MARKER!!!
if (minutes > 90) {
//Here several threads can execute this line
//And service.authenticateWithoutCache() will be called several times and this should not happen.
//If I execute computeIfAbsent it will be evaluated only the
//first time a thread reach this code
// and it won't be updated anymore even if access token expires.
return cachedKeys.compute(accessTokenKey, (key, value) ->
service.authenticateWithoutCache()

});
}

}
return token;
}

最佳答案

您必须将 token 生成放入同步块(synchronized block)中,尝试在该 block 中再次获取它并在每个线程中重试。像这样的东西:

TokenResponse getOrCreateFor(String accessTokenKey){
TokenResponse token = cachedKeys.get(accessTokenKey);
if (token != null)
return token;

synchronized(cachedKeys){
token = cachedKeys.get(accessTokenKey);
if (token != null)
return token;
return cachedKeys.computeIfAbsent(accessTokenKey,
key -> service.authenticateWithoutCache());
}
}

如果您只是在发生超时之前清除 token 并在之后使用该方法,一切都应该没问题:-)

这样,只有 token 的创建是同步的,其他一切都是并行的。

如果你想为不同的用户并行获取 token ,你需要有一个类似于 accesTokenKeys 的 HashSet 之类的东西,每个 accesTokenKey 都有自己的 accesTokenKey 对象,用于锁定authenticateWithoutCache。但对其的访问也必须是线程安全的,也许有一个很好的非锁定解决方案。但我会推迟到需要时才进行。

关于java - 有条件地计算 ConcurentHashMap 中的值并每隔一定时间替换它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44503894/

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