当我计划有效地缓存多个值时,应该如何实现Guava缓存? [英] How should I implement Guava cache when I plan to cache multiple values efficiently?

查看:296
本文介绍了当我计划有效地缓存多个值时,应该如何实现Guava缓存?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个具有Guava LoadingCache< String,Integer> 的Java类,并且在该缓存中,我计划存储两件事:在职员工的平均时间一直为这一天及其效率而努力。我之所以要缓存这些值,是因为每次请求进入时都要计算成本。而且,缓存的内容将每分钟刷新一次( refreshAfterWrite )。

I have a Java class that has a Guava LoadingCache<String, Integer> and in that cache, I'm planning to store two things: the average time active employees have worked for the day and their efficiency. I am caching these values because it would be expensive to compute every time a request comes in. Also, the contents of the cache will be refreshed (refreshAfterWrite) every minute.

在这种情况下,我想使用 CacheLoader ,但是,其加载方法每个键仅加载一个值。在我的 CacheLoader 中,我打算做类似的事情:

I was thinking of using a CacheLoader for this situation, however, its load method only loads one value per key. In my CacheLoader, I was planning to do something like:

private Service service = new Service();

public Integer load(String key) throws Exception {
    if (key.equals("employeeAvg"))
        return calculateEmployeeAvg(service.getAllEmployees());

    if (key.equals("employeeEff"))
        return calculateEmployeeEff(service.getAllEmployees());

    return -1;
}

对我来说,我觉得效率很低,因为为了同时加载两个值,我必须调用 service.getAllEmployees()两次,因为如果我错了,请更正我, CacheLoader 应该

For me, I find this very inefficient since in order to load both values, I have to invoke service.getAllEmployees() twice because, correct me if I'm wrong, CacheLoader's should be stateless.

这让我认为使用 LoadingCache.put(key,value)方法使我可以只需创建一个实用程序方法即可调用一次 service.getAllEmployees()并即时计算值。但是,如果我确实使用 LoadingCache.put(),则我将没有 refreshAfterWrite 功能,因为它取决于

Which made me think to use the LoadingCache.put(key, value) method so I can just create a utility method that invokes service.getAllEmployees() once and calculate the values on the fly. However, if I do use LoadingCache.put(), I won't have the refreshAfterWrite feature since it's dependent on a cache loader.

如何提高效率?

推荐答案

您的问题似乎源于使用字符串表示值类型(有效的Java项目50)。相反,请考虑定义存储此数据的适当值类型,并使用记住供应商 ,以避免重新计算它们。

It seems like your problem stems from using strings to represent value types (Effective Java Item 50). Instead, consider defining a proper value type that stores this data, and use a memoizing Supplier to avoid recomputing them.

public static class EmployeeStatistics {
  private final int average;
  private final int efficiency;
  // constructor, getters and setters
}

Supplier<EmployeeStatistics> statistics = Suppliers.memoize(
    new Supplier<EmployeeStatistics>() {
  @Override
  public EmployeeStatistics get() {
    List<Employee> employees = new Service().getAllEmployees();
    return new EmployeeStatistics(
        calculateEmployeeAvg(employees),
        calculateEmployeeEff(employees));
  }});

您甚至可以将这些计算方法移动到 EmployeeStatistics ,然后将所有员工简单地传递给构造函数,并让它计算适当的数据。

You could even move these calculation methods inside EmployeeStatistics and simply pass in all employees to the constructor and let it compute the appropriate data.

如果需要配置缓存行为超过 Suppliers.memoize() Suppliers.memoizeWithExpiration( ) 可以提供这种相似的模式,这掩盖了您在<$ c $内使用 Cache 的事实c>供应商:

If you need to configure your caching behavior more than Suppliers.memoize() or Suppliers.memoizeWithExpiration() can provide, consider this similar pattern, which hides the fact that you're using a Cache inside a Supplier:

Supplier<EmployeeStatistics> statistics = new Supplier<EmployeeStatistics>() {
  private final Object key = new Object();
  private final LoadingCache<Object, EmployeeStatistics> cache =
      CacheBuilder.newBuilder()
        // configure your builder
        .build(
           new CacheLoader<Object, EmployeeStatistics>() {
             public EmployeeStatistics load(Object key) {
               // same behavior as the Supplier above
             }});

  @Override
  public EmployeeStatistics get() {
    return cache.get(key);
  }};

这篇关于当我计划有效地缓存多个值时,应该如何实现Guava缓存?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆