Java 8引入了两个用于并发累加和累计的工具类:LongAdder和LongAccumulator。它们都是设计用来在高并发环境下提供高效的数字累加和累计操作。
1. LongAdder
LongAdder是AtomicLong的一种替代,特别是当多个线程频繁地进行更新操作时。与AtomicLong相比,LongAdder在高并发环境下提供了更好的性能,但是可能牺牲了一些空间和计算的精度。
使用场景:当多个线程需要频繁地更新一个共享的计数器时,LongAdder是一个很好的选择。
示例:
import java.util.concurrent.atomic.LongAdder;
public class LongAdderDemo {
public static void main(String[] args) {
LongAdder adder = new LongAdder();
adder.add(5);
adder.increment();
System.out.println(adder.sum());
}
}
2. LongAccumulator
LongAccumulator是一个更为通用的工具,它允许您提供一个lambda函数来描述累加的操作。这意味着除了简单的加法,您还可以进行其他操作,如乘法、最大值和最小值等。
使用场景:当您需要一个并发累加器,但是操作不仅仅是简单的加法时,LongAccumulator是一个很好的选择。
示例:
import java.util.concurrent.atomic.LongAccumulator;
public class LongAccumulatorDemo {
public static void main(String[] args) {
// 使用乘法作为累加操作
LongAccumulator accumulator = new LongAccumulator((x, y) -> x * y, 1);
accumulator.accumulate(5);
accumulator.accumulate(3);
System.out.println(accumulator.get()); // 输出15
}
}
注意:虽然LongAdder和LongAccumulator提供了更高的并发性能,但在只有少量线程进行更新操作的情况下,AtomicLong可能会更为高效。
总结:LongAdder和LongAccumulator是Java 8引入的两个强大的并发工具,它们为高并发环境下的累加和累计操作提供了高效的解决方案。当您面临这种情况时,应考虑使用这两个工具类,而不是传统的AtomicLong。
LongAdder 和 LongAccumulator:进阶用法与场景
1. LongAdder的扩展使用
由于LongAdder是为高并发场景设计的,它在内部使用了一个名为Cell的数组来存储部分和,这使得多个线程可以在不同的Cell上进行操作,从而避免争用。但这也意味着获取当前的总和需要遍历整个数组。
统计大量数据:
在某些场景中,您可能需要统计大量数据的频率或分布。例如,您可能需要跟踪网站上每个页面的访问次数。在这种情况下,使用一个HashMap<String, LongAdder>可以为每个页面提供一个高效的并发计数器。
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.LongAdder;
public class PageVisitCounter {
private final ConcurrentHashMap<String, LongAdder> pageVisitCounts = new ConcurrentHashMap<>();
public void visitPage(String page) {
pageVisitCounts.computeIfAbsent(page, k -> new LongAdder()).increment();
}
public long getPageVisitCount(String page) {
return pageVisitCounts.getOrDefault(page, new LongAdder()).sum();
}
}
2. LongAccumulator的扩展使用
由于LongAccumulator可以接受任何二元操作符,这使得其应用场景非常广泛。
找出并发环境下的最大值:
假设您需要在并发环境下找出一系列数字中的最大值。您可以使用LongAccumulator来实现这个需求。
import java.util.concurrent.atomic.LongAccumulator;
public class MaxFinder {
private final LongAccumulator maxAccumulator = new LongAccumulator(Math::max, Long.MIN_VALUE);
public void submit(long value) {
maxAccumulator.accumulate(value);
}
public long getMax() {
return maxAccumulator.get();
}
}
累计产品的销售额:
假设您有一个电商平台,需要跟踪每个产品的销售额。您可以使用LongAccumulator来累计每个产品的销售。
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.LongAccumulator;
public class SalesTracker {
private final ConcurrentHashMap<String, LongAccumulator> productSales = new ConcurrentHashMap<>();
public void recordSale(String product, long amount) {
productSales.computeIfAbsent(product, k -> new LongAccumulator(Long::sum, 0)).accumulate(amount);
}
public long getTotalSales(String product) {
return productSales.getOrDefault(product, new LongAccumulator(Long::sum, 0)).get();
}
}
总结:
LongAdder和LongAccumulator提供了非常灵活和高效的工具,可以应对各种并发场景。正确使用这两个类,可以大大提高并发程序的性能和可靠性。
本文暂时没有评论,来添加一个吧(●'◡'●)