# 43. LongAdder高并发计数优化分析

# 标准答案

✅ LongAdder的优化原理和应用:

  1. 分段计数机制

    • 内部维护多个计数单元(Cell数组)
    • 不同线程更新不同的计数单元
    • 最终结果是所有计数单元的总和
  2. 动态扩展机制

    • 初始只有一个base值
    • 出现竞争时,创建新的计数单元
    • 自适应扩展,减少竞争
  3. 性能优势

    • 相比AtomicLong减少CAS竞争
    • 适合写多读少场景
    • 高并发下性能更好
  4. 使用场景

    • 统计计数(如PV/UV)
    • 性能监控指标
    • 并发度量

# 答案解析

# 1️⃣ LongAdder vs AtomicLong

// 传统实现
public class AtomicCounter {
    private AtomicLong count = new AtomicLong(0);
    
    public void increment() {
        count.incrementAndGet();
    }
    
    public long getCount() {
        return count.get();
    }
}

// LongAdder实现
public class LongAdderCounter {
    private LongAdder count = new LongAdder();
    
    public void increment() {
        count.increment();
    }
    
    public long getCount() {
        return count.sum();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 2️⃣ 性能测试

public class CounterBenchmark {
    private static final int THREADS = 1000;
    private static final int ITERATIONS = 100000;
    
    @Benchmark
    public void testAtomicLong() {
        AtomicCounter counter = new AtomicCounter();
        ExecutorService executor = Executors.newFixedThreadPool(THREADS);
        
        for (int i = 0; i < THREADS; i++) {
            executor.submit(() -> {
                for (int j = 0; j < ITERATIONS; j++) {
                    counter.increment();
                }
            });
        }
    }
    
    @Benchmark
    public void testLongAdder() {
        LongAdderCounter counter = new LongAdderCounter();
        ExecutorService executor = Executors.newFixedThreadPool(THREADS);
        
        for (int i = 0; i < THREADS; i++) {
            executor.submit(() -> {
                for (int j = 0; j < ITERATIONS; j++) {
                    counter.increment();
                }
            });
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# 常见误区

  • 误区1:认为LongAdder在所有场景都优于AtomicLong
  • 误区2:忽视LongAdder的内存开销

# 典型场景与解决方案

# ✅ 高并发统计系统

public class MetricsCollector {
    private final Map<String, LongAdder> metrics = new ConcurrentHashMap<>();
    
    public void recordAccess(String api) {
        // 获取或创建计数器
        metrics.computeIfAbsent(api, k -> new LongAdder())
               .increment();
    }
    
    public Map<String, Long> getMetrics() {
        Map<String, Long> result = new HashMap<>();
        metrics.forEach((key, adder) -> 
            result.put(key, adder.sum())
        );
        return result;
    }
    
    // 定期重置
    @Scheduled(fixedRate = 60000)
    public void reset() {
        metrics.values().forEach(LongAdder::reset);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 企业实战经验

# Situation(业务背景)

大型电商网站需要实时统计各页面的访问量。

# Task(核心任务)

优化高并发场景下的计数性能。

# Action(解决方案)

  1. 使用LongAdder替换AtomicLong
  2. 实现分级统计策略
  3. 采用定期汇总机制
  4. 增加监控告警

# Result(结果)

  • 统计延迟降低90%
  • CPU使用率降低50%
  • 系统吞吐量提升200%

# 深入追问

🔹 LongAdder的内部实现原理是什么?

  • Cell数组分散竞争
  • 动态扩容机制
  • 汇总计算策略

🔹 在什么场景下不适合使用LongAdder?

  • 读多写少场景
  • 需要严格一致性的场景
  • 内存资源受限的场景

# 相关面试题

  1. LongAdder与AtomicLong的区别?
  2. 如何选择合适的计数器实现?
  3. LongAdder的性能优化原理是什么?