如何以线程安全的方式填充字符串的地图和另一个地图



我正在努力使用以下类incrementdecrement指标来测量我的申请指标。

public class AppMetrics {
  private final AtomicLongMap<String> metricCounter = AtomicLongMap.create();
  private static class Holder {
    private static final AppMetrics INSTANCE = new AppMetrics();
  }
  public static AppMetrics getInstance() {
    return Holder.INSTANCE;
  }
  private AppMetrics() {}     
  public void increment(String name) {
    metricCounter.getAndIncrement(name);
  }
  public AtomicLongMap<String> getMetricCounter() {
    return metricCounter;
  }
}

我正在调用来自多线程代码的AppMetrics类的increment方法,以通过度量名称来增加指标。

问题语句:

现在,我想为每个字符串的clientId拥有metricCounter。这意味着我们也可以多次获得相同的clientId,有时它将是一个新的clientId,因此以某种方式我需要为该clientId提取metricCounter映射,并在该特定地图上提取指标(这是我不确定如何做的事情那)。

牢记这一点的正确方法是什么,它必须是安全的,并且必须执行原子操作。我当时想制作这样的地图:

  private final Map<String, AtomicLongMap<String>> clientIdMetricCounterHolder = Maps.newConcurrentMap();

这是正确的方法吗?如果是,那么如何通过传递clientId来填充此地图,因为它的值将是每个指标的计数器地图。

我在Java 7。

如果使用地图,则需要同步创建新的AtomicLongMap实例。我建议改用LoadingCache。您可能最终不会使用任何实际的"缓存"功能,但是"加载"功能非常有用,因为它将为您同步AtomicLongMap实例的创建。例如:

LoadingCache<String, AtomicLongMap<String>> clientIdMetricCounterCache =
        CacheBuilder.newBuilder().build(new CacheLoader<String, AtomicLongMap<String>>() {
            @Override
            public AtomicLongMap<String> load(String key) throws Exception {
                return AtomicLongMap.create();
            }
        });

现在,您可以安全地开始对任何客户端进行更新度量计数,而不必担心客户端是否是新的。例如

clientIdMetricCounterCache.get(clientId).incrementAndGet(metricName);

a Map<String, Map<String, T>>只是伪装中的 Map<Pair<String, String>, T>。创建MultiKey类:

class MultiKey {
    public String clientId;
    public String name;
    // be sure to add hashCode and equals
}

然后只使用AtomicLongMap<MultiKey>

编辑:

提供指标集的定义很好,使用此数据结构来查看一个客户端的指标并不难:

Set<String> possibleMetrics = // all the possible values for "name"
Map<String, Long> getMetricsForClient(String client) {
    return Maps.asMap(possibleMetrics, m -> metrics.get(new MultiKey(client, m));
}

返回的地图将是实时无法解码的视图。如果您使用较旧的Java版本,可能会有些详细,但仍然有可能。

相关内容

最新更新