【问题标题】:Map of AtomicIntegerAtomicInteger 的映射
【发布时间】:2014-01-19 21:21:42
【问题描述】:

我想实现一个共享对象来计算操作执行的统计信息。 对象状态将由Map<String,AtomicInteger> 表示(key 是操作的名称,value 是操作执行的次数)。我是否正确,我可以选择一个 HashMap<String,AtomicInteger> 实现并且不使用同步来从中获取值,因为 AtomicInteger 在它下面有一个 volatile value 字段。

增加和增加执行统计的代码示例:

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

public final class Stats {

private final Map<String, AtomicInteger> statistics = new HashMap<String, AtomicInteger>();

public int increment(String operationName) {
    if (!statistics.containsKey(operationName)) {
        synchronized (statistics) {
            if (!statistics.containsKey(operationName)) 
                statistics.put(operationName, new AtomicInteger(0));
        }
    }

    return statistics.get(operationName).getAndIncrement();
}

public int getOpStats(String operationName) {
    if (!statistics.containsKey(operationName)) {
        return 0;
    }
    return statistics.get(operationName).get();
}

}

【问题讨论】:

  • 不清楚你想问什么。请尝试提出一个具体的问题。
  • 这个不用自己实现,从key->int的线程安全映射已经存在于Guava的ConcurrentHashMultiset

标签: java multithreading synchronization


【解决方案1】:

如果您想在计数器初始化方面保持线程安全,您应该使用ConcurrentHashMap 并始终以这种方式实例化并增加计数器:

themap.putIfAbsent("the name", new AtomicInteger(0)); 
themap.get("the name").incrementAndGet();

您还可以确保在开始之前初始化所有使用的计数器,然后使用您喜欢的任何集合。一个普通的AtomicInteger[]-array 是迄今为止最快的,因为你知道在哪里看,HashTable 可能比HashMap 稍微快一些。

如果您事先知道您有哪些计数器,您还可以定义所有计数器名称的 java enum 并使用 EnumMap&lt;YourCountersEnum, AtomicInteger&gt;。这可能会提供接近AtomicInteger[]-array 查找的查找性能。

【讨论】:

  • 如果你这样做,你必须确保你 putIfAbsent 一个 AtomicInteger(1) 而不是 0!
  • @Voo 不!如果你这样做,你第一次初始化计数器时会得到 2。您总是通过 incrementAndGet 无条件地递增它们,但如果它们为空则创建它们。 “空 == 零”。也咬我。
  • 啊,好吧,显然,如果你愿意,你可以随时创建 AtomicInteger,而且它可能不会特别昂贵 - 看起来仍然相当浪费,但可以。
  • 如果对象已经存在,putIfAbsent 会更便宜。增加一个数字并不是那么昂贵(这就是它有一种方法的原因)。这是两个 volatile 查找在这里的开销很大。
  • 这样不是更好吗? x = putIfAbsent(..., new AtomicInteger(1)); if (x != null) x.incrementAndGet();
猜你喜欢
  • 2020-07-23
  • 2019-02-26
  • 1970-01-01
  • 1970-01-01
  • 2020-01-31
  • 1970-01-01
  • 2012-07-11
  • 1970-01-01
  • 2020-06-13
相关资源
最近更新 更多