java - 计数器在千分尺中是线程安全的吗
问题描述
我正在尝试发布我的应用正在处理的事件数量。这是我在接收端的代码:
public void process(List<String> batch) {
logger.info ("Processing batch of size " + batch.size())
metrics.incrementCounter(MetricsType.CONSUMER_TOTAL_PROCESSED, batch.size)
}
类 Metrics 是:
public class Metrics {
private static final Map<MetricsType, Counter> COUNTER_MAP = new ConcurrentHashMap<>();
public Metrics(
@Autowired MeterRegistry meterRegistry
) {
COUNTER_MAP.put(
MetricsType.CONSUMER_TOTAL_PROCESSED,
Counter.builder("CONSUMER_TOTAL_PROCESSED").register(meterRegistry)
);
COUNTER_MAP.put(
MetricsType.CONSUMER_DUPLICATE_PROCESSED,
Counter.builder("CONSUMER_DUPLICATE_PROCESSED").register(meterRegistry)
);
}
public void increment(MetricsType metricsType, int size) {
COUNTER_MAP.get(metricsType).increment(size);
}
}
枚举MetricsType
包含所有类型的计数器。
该process
方法随时被 16 个线程调用。我面临的问题是打印计数的记录器,而在 grafana 中报告的总计数还有很长的路要走。
每次增加计数器时都必须同步吗?
编辑 - 我的意思是计数关闭是,如果有两个大小为 200 的日志,那么 grafana 应该报告总计数器 400。我通过花费 2 小时的时间范围来验证这一点,我从日志中提取所有大小并添加它们。
如果您偶然发现这一点并看到两个来源之间的差异,请检查您在 Grafana 中的最大数据点数是多少,这就是我认为计数器可能不是线程安全的实际问题。
解决方案
计数器是线程安全的,在内部它们使用一些原子数据结构进行计数。鉴于您的代码,我怀疑记录器打印的内容与您在 grafana 中看到的完全不同,因为记录器打印当前批次的大小,而计数器打印所有批次大小的总和。
推荐阅读
- ruby - print inside 放入 Ruby
- c# - HTMLAgilityPack - 按类获取类中的元素
- python - 如何从我的数据表数组中删除 'b'\xef\xbb\xbf'?
- java - 如何正确施法?
- java - 在 Java 中使用类类型变量作为泛型
- mysql - 如何找到具有特定值的按列计数
- php - 从数据库中选择选项
- javascript - 为什么 Date.toString 的时区表示在 Node/Chrome 中发生了变化,我该如何改回来?
- android - 从pdf中获取drawable
- javascript - 在 ajax 响应的下拉列表中设置选定的值(来自数据库的值)