首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何实现以命中次数为值的Guava Cache?

如何实现以命中次数为值的Guava Cache?
EN

Stack Overflow用户
提问于 2018-10-08 21:50:53
回答 3查看 1.9K关注 0票数 3

我正在尝试实现一个缓存,它将统计过去5分钟内登录尝试的次数,在我的代码中,我想检查用户尝试的次数是否超过了MAX_ATTEMPTS。

在我为"Guava Cache“在线找到的所有代码示例中,使用load方法从其他来源获取值或使用某种方法计算它,我如何在每次缓存命中时递增它?

代码语言:javascript
复制
static LoadingCache<String, Integer> cache = CacheBuilder.newBuilder()
    .maximumSize(100000)
    .expireAfterAccess(5, TimeUnit.MINUTES)
    .build(
            new CacheLoader<String, Integer>() {
                public Integerload(String user) {
                       return ????;
                }
            }
    );

稍后在运行时,我想检查一下:

代码语言:javascript
复制
if(cache.getIfPresent(user) != null && cache.get(user) > MAX_ATTEMPTS)

如果满足以下条件,还会递增它:

代码语言:javascript
复制
if(cache.getIfPresent(user) != null && cache.get(user) <= MAX_ATTEMPTS)
EN

回答 3

Stack Overflow用户

发布于 2018-10-10 21:46:09

@Oren你的解决方案不是线程安全的,因为你是在Cache之外的值上操作。最好使用Cache#asMap()视图,并在ConcurrentMap#compute(K, BiFunction)方法中更改值:

代码语言:javascript
复制
forgetPasswordCache.asMap().compute(email, (cachedEmail, currentCount) -> {
  if (currentCount != null && currentCount >= RESET_PASSWORD_MAX_ATTEMPTS) {
    logger.error("User with id: " + user.getId() + " and email: " + email +
         " has reached the maximum number of reset password attempts, the mail will not be sent");
    return null;
  }

  if (currentCount == null) {
    return 1;
  } else {
    return currentCount + 1;
  }
});
票数 3
EN

Stack Overflow用户

发布于 2018-10-09 16:08:38

您可以尝试改编以下代码片段:

代码语言:javascript
复制
public class Demo {
    public static void main(String[] x) {
        CacheLoader<String, AtomicInteger> initialValueLoader = new CacheLoader<String, AtomicInteger>() {
            @Override
            public AtomicInteger load(String key) {
                // do not care of the key. everybody starts with 0 login attempts.
                return new AtomicInteger(0);
            }
        };

        LoadingCache<String, AtomicInteger> c = CacheBuilder
            .newBuilder()
            .maximumSize(100000)
            .expireAfterAccess(2, TimeUnit.SECONDS)
            .build(initialValueLoader);

        String user = "bob";

        try {
            // when the user tries to login, increment the attemps by one
            Verify.verify(c.get(user).incrementAndGet() == 1);

            // next call will get one
            Verify.verify(c.get(user).get() == 1);
        } catch (ExecutionException e) {
            throw new RuntimeException("oups: " + e, e);
        }

        // simulate time
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
        }

        // after some time, the cache is cleared
        try {
            Verify.verify(c.get(user).get() == 0);
        } catch (ExecutionException e) {
            throw new RuntimeException("oups: " + e, e);
        }

        System.out.println("done.");
    }
}
票数 1
EN

Stack Overflow用户

发布于 2018-10-09 17:07:33

通过仅使用Guava的缓存功能解决了问题(不使用加载器)

缓存如下所示:

代码语言:javascript
复制
public class ForgetPasswordAttemptsCache {

    private static final Cache<String, Integer> forgetPasswordCache = CacheBuilder.newBuilder()
            .expireAfterAccess(24, TimeUnit.HOURS)
            .build();

    private ForgetPasswordAttemptsCache(){
    }

    public static Cache<String, Integer> getInstance() {
        return forgetPasswordCache;
    }

}

以及它的用法:

代码语言:javascript
复制
final String email = user.getEmail();
Integer currentCount = ForgetPasswordAttemptsCache.getInstance().getIfPresent(email);

if (currentCount != null && currentCount >= RESET_PASSWORD_MAX_ATTEMPTS) {
    logger.error("User with id: " + user.getId() + " and email: " + email +
            " has reached the maximum number of reset password attempts, the mail will not be sent");
    return;
}

if (currentCount == null) {
    ForgetPasswordAttemptsCache.getInstance().put(email, new Integer(1));
} else {
    ForgetPasswordAttemptsCache.getInstance().put(email, new Integer(currentCount + 1));
}

感谢spi提供的解决方案。(现在我正在寻找一种方法来测试它,而不需要24小时运行的测试。)

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

https://stackoverflow.com/questions/52703795

复制
相关文章

相似问题

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