当您必须从数据中提供多个结果时,如何最佳地使用 Guava Cache?

如何解决当您必须从数据中提供多个结果时,如何最佳地使用 Guava Cache?

我有一个缓存加载器,它缓存来自 API 的响应(以列表的形式)。现在我的函数不需要直接响应数据,所以我创建了一个提供程序,它可以处理这些原始响应并充当预言机,允许我发送所需的数据而不是整个列表。

我当前方法的问题是,对于每个这样的响应,即使列表与以前相同,提供者也必须遍历整个列表;这使得每次调用的复杂度为 O(n) 而不是我想要的 O(1)。

我能想到的潜在解决方

  1. 改为缓存已处理的数据。现在的问题是,在这种情况下我需要两个不同的缓存,并且每次刷新都会从 API 中不必要地从两个缓存中获取相同的结果。
  2. 仅在缓存值已更改时才在提供程序中迭代 我想这样做,但我找不到一种方法来知道缓存是否更改了值,我所有的方法都需要传递再次花费 O(n) 时间的数据。

谁能提出解决这个问题的好方法

规则信息缓存加载器类


import com.google.common.cache.CacheLoader;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.annotation.ParametersAreNonnullByDefault;

final class RuleInfoLoader extends CacheLoader<RuleType,List<RuleInfo>> {
  private final ConfigServiceGrpc.ConfigServiceBlockingStub configServiceBlockingStub;
  private final long callTimeout;

  RuleInfoLoader(ConfigServiceClientConfig clientConfig) {
    callTimeout = clientConfig.getCallTimeout();
    configServiceBlockingStub = ConfigServiceGrpc.newBlockingStub();
  }

  @Override
  @ParametersAreNonnullByDefault
  public List<RuleInfo> load(RuleType ruleType) {
    return fetchRuleInfo(ruleType);
  }

  private List<RuleInfo> fetchRuleInfo(RuleType ruleType) {
    return configServiceBlockingStub
        .withDeadlineAfter(callTimeout,TimeUnit.MILLISECONDS)
        .getAnomalyRuleInfos(
            GetRuleInfosRequest.newBuilder().setRuleType(ruleType).build())
        .getRuleInfosList();
  }
}

规则信息提供者

import com.google.common.cache.CacheLoader;
import com.google.common.collect.ImmutableMap;
import com.typesafe.config.Config;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

public class RuleInfoProvider {
  private LoadingCache<RuleType,List<RuleInfo>> ruleInfoCache;

  public RuleInfoProvider(Config config) {
    initCache(config);
  }

  public Map<String,RuleInfo> getRuleMapping() {
    ImmutableMap.Builder<String,RuleInfo> mapBuilder = new ImmutableMap.Builder<>();
    getRuleInfo(RuleType.a)
        .forEach(rule -> mapBuilder.put(rule.getRuleId(),rule));
    getRuleInfo(RuleType.b)
        .forEach(rule -> mapBuilder.put(rule.getRuleId(),rule));
    getRuleInfo(RuleType.c)
        .forEach(rule -> mapBuilder.put(rule.getRuleId(),rule));
    return mapBuilder.build();
  }

  public Map<Class<? extends RuleInfo>,List<String>> getPathsMapping() {
    return new ImmutableMap.Builder<Class<? extends RuleInfo>,List<String>>()
        .put(
            Class_A.class,getRuleInfo(RuleType.a).stream()
                .map(RuleInfo::getPath)
                .collect(Collectors.toList()))
        .put(
            Class_B.class,getRuleInfo(RuleType.b).stream()
                .map(RuleInfo::getPath)
                .collect(Collectors.toList()))
        .put(
            Class_c.class,getRuleInfo(RuleType.c).stream()
                .map(RuleInfo::getPath)
                .collect(Collectors.toList()))
        .build();
  }

  private List<RuleInfo> getRuleInfo(RuleType ruleType) {
    try {
      return ruleInfoCache.get(ruleType);
    } catch (Exception e) {
      return Collections.emptyList();
    }
  }
  
  private void initCache(Config config) {
    ruleInfoCache =
        CacheBuilder.newBuilder()
            .refreshAfterWrite(config.getCacheConfig().getRefreshMs())
            .maximumSize(config.getCacheConfig().getMaxSize())
            .build(
                CacheLoader.asyncReloading(
                    new RuleInfoLoader(config.getConfigServiceClientConfig()),Executors.newSingleThreadScheduledExecutor()));
  }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?