# 43. LongAdder高并发计数优化分析
# 标准答案
✅ LongAdder的优化原理和应用:
分段计数机制:
- 内部维护多个计数单元(Cell数组)
- 不同线程更新不同的计数单元
- 最终结果是所有计数单元的总和
动态扩展机制:
- 初始只有一个base值
- 出现竞争时,创建新的计数单元
- 自适应扩展,减少竞争
性能优势:
- 相比AtomicLong减少CAS竞争
- 适合写多读少场景
- 高并发下性能更好
使用场景:
- 统计计数(如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
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
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
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(解决方案)
- 使用LongAdder替换AtomicLong
- 实现分级统计策略
- 采用定期汇总机制
- 增加监控告警
# Result(结果)
- 统计延迟降低90%
- CPU使用率降低50%
- 系统吞吐量提升200%
# 深入追问
🔹 LongAdder的内部实现原理是什么?
- Cell数组分散竞争
- 动态扩容机制
- 汇总计算策略
🔹 在什么场景下不适合使用LongAdder?
- 读多写少场景
- 需要严格一致性的场景
- 内存资源受限的场景
# 相关面试题
- LongAdder与AtomicLong的区别?
- 如何选择合适的计数器实现?
- LongAdder的性能优化原理是什么?