Java 使用长加法器计算统计计数器的最大值?

Java 使用长加法器计算统计计数器的最大值?,java,concurrency,statistics,java-8,java.util.concurrent,Java,Concurrency,Statistics,Java 8,Java.util.concurrent,我们使用原子收集一些统计数据。一些用户看到了关于这些问题的争论,建议改用LongAdder。但是,我看不到计算最大值的方法,因为我们目前正在使用原子: AtomicLong _current, _total, _max; ... void add(long delta) { long current = _current.addAndGet(delta); if (delta>0) { _total.addAndGet(delta); long max = _

我们使用原子收集一些统计数据。一些用户看到了关于这些问题的争论,建议改用LongAdder。但是,我看不到计算最大值的方法,因为我们目前正在使用原子:

AtomicLong _current, _total, _max;
...

void add(long delta)
{
  long current = _current.addAndGet(delta);
  if (delta>0)
  {
    _total.addAndGet(delta);
    long max = _max.get();
    while (current > max)
    {
      if (_max.compareAndSet(max, current))
        break;
      max = _max.get();
    }
 }
因此,我认为我们可以很容易地用一个长加法器来替换
\u total
,但因为我们使用的是
\u current.addAndGet(delta)
,这对于
长加法器
来说是不好的,我们也不能对“\u max”值进行cas操作

基于
LongAdder
或类似的可伸缩无锁结构,有没有收集此类统计数据的好算法


事实上,当我问的时候,我们的数据通常会更新6到10个原子。如果我们仍然看到了争用,那么抓取一个锁并更新6到10个正常的Long是否可能更好?

您不需要
LongAdder
,但是
longamperator
这里:您需要
新的longamperator(数学::max,Long.MIN_值)
,这在这里做得对
LongAdder
LongAccumulator

Ah的一个特例,它允许将
\u max
转换为
LongAccumulator
,但它无助于
\u current
所需的addAndGet语义。但是,它仍然允许用1个AtomicLong、1个LongAdder和1个AtomicLong替换3个AtomicLongLongAccumulator@gregw:是否可以进一步简化,取决于您在发布的方法之外对这些值实际执行的操作。从您所展示的单一方法中,所有三个都将始终包含相同的值,因此,可以用一个
LongAdder
…@Holger替换。这三个值并不总是相同的,因为可以传入负增量。@gregw:我明白了。这让我想知道实际的用例。如果此时假设争用较高,实际结果取决于不可预测的线程调度,因为累积
-1、+1、+1、+1
将产生与累积
+1、+1、-1、-1
不同的最大值,即使只有纳秒产生差异(我们实际上可能同时遇到所有四个值,但是
AtomicLong
强制执行任意的串行更新顺序)…