映射的Java Threadsafe增量值

问题描述 投票:0回答:2

我想增加不存在的值,并增加它的存在。而且我有很多线程,因此应该是线程安全的。

我喜欢这样:

private ConcurrentHashMap<Long, LongAdder> map = new ConcurrentHashMap<>();

public void increment() {
    Long key = timeRoundService.roundToSecond(Instant.now());//round seconds
    map.computeIfAbsent(key, (k) -> new LongAdder()).add(1);
}

但是它没有用。我做错了什么?

java multithreading thread-safety java.util.concurrent
2个回答
0
投票

我认为问题可能出在sum的语义上。该方法的javadoc指出:

“返回当前总和。返回的值不是原子快照;在没有并发更新的情况下调用会返回准确的结果,但是可能不会合并在计算总和时发生的并发更新。”

[如果在另一个线程可能正在调用您的sum()的情况下在映射中的LongAdder上调用increment(),则可能无法获得完整的总和。

(此代码我看不到任何其他问题。它几乎与LongAdder javadoc中的示例相同。]


-1
投票

我将具有[[synchronized]]方法,以便没有冲突的键。我认为您的问题是您有重复的密钥。private Map<Long, LongAdder> map = new HashMap<>(); public synchronized void increment() { Long key = timeRoundService.roundToSecond(Instant.now());//round seconds map.computeIfAbsent(key, (k) -> new LongAdder()).add(1); }

这样,每次有一个线程将访问该方法,因此您不会有重复的键

您可以尝试使用:

private static Map<Long, LongAdder> map = new HashMap<>(); public static synchronized void increment() { Long key = Instant.now().truncatedTo(ChronoUnit.SECONDS).getLong(INSTANT_SECONDS);//round seconds map.computeIfAbsent(key, (k) -> new LongAdder()).add(1); } public static void main(String[] args) throws IOException { for (int i = 0; i < 100; i++) { Thread thread = new Thread(() -> { increment(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } }); thread.run(); } System.out.println(map); }

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.