本文介绍了当我计划有效地缓存多个值时,应该如何实现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()或可以提供这种相似的模式,这掩盖了您在<$ 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缓存?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-27 15:44