java - 并发频率计数器-并发问题

标签 java concurrency

我想用 Java 创建一个并发频率计数器类。

一旦处理了请求(通过 processRequest 方法),代码就会检查请求的类型(整数)并计算给定时间内已处理的请求数量(按请求类型分组)。 processRequest方法会被多个线程同时调用。

还有另外两种方法:

  • clearMap():每3小时由一个线程调用,清除整个 map 。
  • getMap():Web 服务可以随时调用它,并返回频率图当前状态的不可变副本。

请参阅下面我实现该计划的初步计划。

public class FrequencyCounter {

     private final ConcurrentHashMap<Integer,Long> frequencenyMap = new ConcurrentHashMap<>();

     public void processRequest(Request request){
         frequencenyMap.merge(request.type, 0L, (v, d) -> v+1);
     }

     public void clearMap(){
         frequencenyMap.clear();
     }

     public Map<Integer,Long> getMap(){
         return ImmutableMap.copyOf(frequencenyMap);
     }
}

我检查了ConcurrentHashMap的文档,它告诉我们merge方法是原子执行的。

因此,一旦clear()方法开始清除映射的哈希桶(根据哈希桶锁定),当另一个线程在获取频率映射的值和增加其值之间时,它就不能被调用processRequest 方法,因为 merge 方法是原子执行的。

我说得对吗? 我上面的方案看起来还可以吗?

谢谢你的建议。

最佳答案

首先,替换Long AtomicLong .

第二,使用 computeIfAbsent .

 private final Map<Integer, AtomicLong> frequencyMap = new ConcurrentHashMap<>();

 public void processRequest(Request request){
     frequencyMap.computeIfAbsent(request.type, k -> new AtomicLong())
                 .incrementAndGet();
 }

我相信这是一个更好的解决方案有几个原因:

  1. 问题中的代码使用盒装对象,即 (v, d) -> v+1真是(Long v, Long d) -> Long.valueOf(v.longValue() + 1) .

    该代码会生成额外的垃圾,可以通过使用 AtomicLong 来避免。 .

    这里的代码只为每个键分配一个对象,并且不需要任何额外的分配来增加计数器,例如即使计数器达到数百万,它仍然只是一个对象。

  2. 拆箱、加 1、装箱操作可能会比严格编码的 incrementAndGet() 花费稍长的时间。操作,增加了碰撞的可能性,需要在 merge 中重试方法。

  3. 代码“纯度”。使用一种接受“值”的方法,然后完全忽略它,对我来说似乎是错误的。这是不必要的代码噪音。

这些当然是我的意见。您可以做出自己的决定,但我认为这段代码阐明了目的,即增加 long计数器,以完全线程安全的方式。

关于java - 并发频率计数器-并发问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55883900/

相关文章:

java - 阻止标题 View 在 ListView 中被单击?

java - 从同步方法调用同步方法的同步成本是多少?

concurrency - Java 11 HttpClient Http2流太多错误

java - 单击按钮更改 TextView LayoutParameters

java - 在 Android 上将我的应用程序置于后台后如何恢复以前的应用程序

Java在真正内存不足之前抛出内存不足异常?

java - 如何在 Eclipse 运行时使用 GAE 模块的共享库?

c++ - std::call_once,应该什么时候用?

Haskell: 'atomicModifyIORef' 是如何工作的?

swift - 使用 URLSession 并发处理后端验证错误