Java并发编程(十三)-累加器
参考文献
累加器
-
AtomicLong
:这是最基本的累加器,支持单个long类型的原子性操作.适用于低并发场景或单线程环境. -
LongAdder
:相比于AtomicLong
,LongAdder
在高并发环境中的性能更好,因为它使用了分段锁来避免多个线程同时竞争一个变量的情况.适用于高并发场景下的计数器或统计器. -
DoubleAdder
:与LongAdder
类似,但支持double类型的原子性操作.适用于需要累加double类型数据的高并发场景. -
LongAccumulator
:支持任意函数的原子性操作,可以自定义累加函数.适用于需要累加的场景比较复杂,需要自定义累加函数的情况. -
DoubleAccumulator
:与LongAccumulator
类似,但支持double类型的原子性操作. -
这些累加器在多线程环境下都可以保证线程安全,可以用于实现高性能的计数器、统计器等场景.选择哪种累加器要根据具体的场景和需求来确定.
-
如果需要进行高并发的累加操作,可以选择
LongAdder
或DoubleAdder
; -
如果需要自定义累加函数,可以选择
LongAccumulator
或DoubleAccumulator
.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
26import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.concurrent.atomic.LongAccumulator ;
public class Example {
public static void main(String[] args) throws IOException {
LongAccumulator accumulator = new LongAccumulator (
(x, y) -> x + y, 0L);
try (BufferedReader reader = new BufferedReader(new FileReader("input.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
String[] words = line.split("\\s+");
for (String word : words) {
if (word.length() >= 5) {
accumulator.accumulate(1L);
}
}
}
}
long result = accumulator.get();
System.out.println("单词出现次数:" + result);
}
}
-
LongAdder
LongAdder
是Java中用于高并发场景下的计数器,它是JDK1.8中新增的类.相较于AtomicLong
,它的性能更好,尤其是在高并发场景下.
实现原理
-
LongAdder
的原理是将一个long类型的值分解成多个小的值,每个线程对这些小的值进行累加,最终将它们汇总起来得到最终结果.这个过程中使用了一种特殊的算法:分段累加算法(Striped64算法). -
具体来说,
LongAdder
内部维护了一个Cell数组,每个Cell都是一个long类型的变量.当多个线程同时对LongAdder
进行累加操作时,它们会被分配到不同的Cell中进行累加操作,这样就避免了多个线程同时对同一个变量进行竞争的情况,从而提高了并发性能. -
当需要获取
LongAdder
的值时,它会将所有Cell中的值相加,再加上一个基础值(base),得到最终结果.这个过程中,需要使用一个类似于volatile的机制来保证各个线程的操作的可见性和有序性. -
总的来说,
LongAdder
的原理是通过将long类型的值分解成多个小的值,使用分段累加算法来避免多个线程的竞争,并使用volatile机制来保证操作的可见性和有序性.这样就能实现高并发场景下的高性能累加器.