Java 中的 累加器(Accumulator) 是 java.util.concurrent.atomic
包中提供的一种高效的工具,用于在多线程环境下进行累加操作。累加器的主要实现类是 LongAdder
和 DoubleAdder
,它们在高并发场景下比传统的 AtomicLong
和 AtomicDouble
性能更好。
1. 累加器的背景
- 在高并发场景下,使用
AtomicLong
或AtomicDouble
进行累加操作时,可能会因为大量线程竞争同一个变量而导致性能下降。 - 累加器通过将单个变量拆分为多个变量(称为 Cell),每个线程操作自己的 Cell,从而减少竞争,提高性能。
- 在需要获取最终结果时,累加器会将所有 Cell 的值累加起来。
2. LongAdder
- 特点:
- 用于对
long
类型进行高效的累加操作。 - 适合高并发场景下的计数器、统计等需求。
- 性能优于
AtomicLong
,但在低并发场景下可能不如AtomicLong
。
- 用于对
- 常用方法:
add(long x)
:累加一个值。increment()
:累加 1。decrement()
:累减 1。sum()
:返回当前的总和。reset()
:重置累加器为 0。sumThenReset()
:返回当前的总和并重置累加器为 0。
- 示例代码:
import java.util.concurrent.atomic.LongAdder; public class LongAdderExample { public static void main(String[] args) { LongAdder adder = new LongAdder(); // 多个线程并发累加 Runnable task = () -> { for (int i = 0; i < 1000; i++) { adder.increment(); } }; Thread thread1 = new Thread(task); Thread thread2 = new Thread(task); thread1.start(); thread2.start(); try { thread1.join(); thread2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Final sum: " + adder.sum()); // 输出 2000 } }
3. DoubleAdder
- 特点:
- 用于对
double
类型进行高效的累加操作。 - 与
LongAdder
类似,适合高并发场景下的浮点数累加。
- 用于对
- 常用方法:
add(double x)
:累加一个值。sum()
:返回当前的总和。reset()
:重置累加器为 0。sumThenReset()
:返回当前的总和并重置累加器为 0。
- 示例代码:
import java.util.concurrent.atomic.DoubleAdder; public class DoubleAdderExample { public static void main(String[] args) { DoubleAdder adder = new DoubleAdder(); // 多个线程并发累加 Runnable task = () -> { for (int i = 0; i < 1000; i++) { adder.add(1.5); } }; Thread thread1 = new Thread(task); Thread thread2 = new Thread(task); thread1.start(); thread2.start(); try { thread1.join(); thread2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Final sum: " + adder.sum()); // 输出 3000.0 } }
4. 累加器与 AtomicLong
的对比
- 性能:
- 在高并发场景下,
LongAdder
和DoubleAdder
的性能优于AtomicLong
和AtomicDouble
,因为它们减少了线程竞争。 - 在低并发场景下,
AtomicLong
和AtomicDouble
的性能可能更好,因为它们没有额外的 Cell 拆分开销。
- 在高并发场景下,
- 适用场景:
- 累加器:适合高并发场景下的计数器、统计等需求。
AtomicLong
:适合低并发场景或需要精确原子操作的场景。
5. 总结
LongAdder
和DoubleAdder
是 Java 中高效的累加器实现,适合高并发场景下的累加操作。- 它们通过减少线程竞争来提高性能,但在低并发场景下可能不如
AtomicLong
和AtomicDouble
。 - 如果需要在高并发环境下进行累加操作,累加器是一个非常好的选择。
6. 扩展:LongAccumulator
和 DoubleAccumulator
LongAccumulator
和DoubleAccumulator
是更通用的累加器实现,允许自定义累加函数。- 示例代码:
import java.util.concurrent.atomic.LongAccumulator; public class LongAccumulatorExample { public static void main(String[] args) { LongAccumulator accumulator = new LongAccumulator((x, y) -> x + y, 0); // 多个线程并发累加 Runnable task = () -> { for (int i = 0; i < 1000; i++) { accumulator.accumulate(1); } }; Thread thread1 = new Thread(task); Thread thread2 = new Thread(task); thread1.start(); thread2.start(); try { thread1.join(); thread2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Final sum: " + accumulator.get()); // 输出 2000 } }
- 适用场景:
- 适合需要自定义累加逻辑的场景,如求最大值、最小值等。
THE END
暂无评论内容