日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[JDK8]性能优化之使用LongAdder替换AtomicLong

發布時間:2025/7/14 编程问答 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [JDK8]性能优化之使用LongAdder替换AtomicLong 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

如果讓你實現一個計數器,有點經驗的同學可以很快的想到使用AtomicInteger或者AtomicLong進行簡單的封裝。

因為計數器操作涉及到內存的可見性和線程之間的競爭,而Atomic***的實現完美的屏蔽了這些技術細節,我們只需要執行相應的方法,就能實現對應的業務需求。

Atomic**雖然好用,不過這些的操作在并發量很大的情況下,性能問題也會被相應的放大。我們可以先看下其中getAndIncrement的實現代碼

public final long getAndIncrement() {return unsafe.getAndAddLong(this, valueOffset, 1L); }// unsafe類中的實現 public final long getAndAddLong(Object var1, long var2, long var4) {long var6;do {var6 = this.getLongVolatile(var1, var2);} while(!this.compareAndSwapLong(var1, var2, var6, var6 + var4));return var6; }

很顯然,在getAndAddLong實現中,為了實現正確的累加操作,如果并發量很大的話,cpu會花費大量的時間在試錯上面,相當于一個spin(自旋)的操作。如果并發量小的情況,這些消耗可以忽略不計。

既然已經意識到Atomic***有這樣的業務缺陷,Doug Lea大神又給我們提供了LongAdder,內部的實現有點類似ConcurrentHashMap的分段鎖,最好的情況下,每個線程都有獨立的計數器,這樣可以大量減少并發操作。

下面通過JMH比較一下AtomicLong 和 LongAdder的性能。

@OutputTimeUnit(TimeUnit.MICROSECONDS) @BenchmarkMode(Mode.Throughput) public class Main {private static AtomicLong count = new AtomicLong();private static LongAdder longAdder = new LongAdder();public static void main(String[] args) throws Exception {Options options = new OptionsBuilder().include(Main.class.getName()).forks(1).build();new Runner(options).run();}@Benchmark@Threads(10)public void run0(){count.getAndIncrement();}@Benchmark@Threads(10)public void run1(){longAdder.increment();} }

1、設置BenchmarkMode為Mode.Throughput,測試吞吐量
2、設置BenchmarkMode為Mode.AverageTime,測試平均耗時

?

線程數為1

1、吞吐量

Benchmark Mode Cnt Score Error Units Main.run0 thrpt 5 154.525 ± 9.767 ops/us Main.run1 thrpt 5 89.599 ± 7.951 ops/us

2、平均耗時

Benchmark Mode Cnt Score Error Units Main.run0 avgt 5 0.007 ± 0.001 us/op Main.run1 avgt 5 0.011 ± 0.001 us/op

單線程情況:
1、AtomicLong的吞吐量和平均耗時都占優勢

?

線程數為10

1、吞吐量

Benchmark Mode Cnt Score Error Units Main.run0 thrpt 5 37.780 ± 1.891 ops/us Main.run1 thrpt 5 464.927 ± 143.207 ops/us

2、平均耗時

Benchmark Mode Cnt Score Error Units Main.run0 avgt 5 0.290 ± 0.038 us/op Main.run1 avgt 5 0.021 ± 0.001 us/op

并發線程為10個時:

  • LongAdder的吞吐量比較大,是AtomicLong的10倍多。
  • LongAdder的平均耗時是AtomicLong的十分之一。

?

線程數為30

1、吞吐量 Benchmark Mode Cnt Score Error Units Main.run0 thrpt 5 36.215 ± 2.341 ops/us Main.run1 thrpt 5 486.630 ± 26.894 ops/us

2、平均耗時

Benchmark Mode Cnt Score Error Units Main.run0 avgt 5 0.792 ± 0.021 us/op Main.run1 avgt 5 0.063 ± 0.002 us/op

線程數為30個時:

  • LongAdder的吞吐量比較大,也是AtomicLong的10倍多。
  • LongAdder的平均耗時也是AtomicLong的十分之一。

總結

一些高并發的場景,比如限流計數器,建議使用LongAdder替換AtomicLong,性能可以提升不少。

轉載于:https://www.cnblogs.com/Joy-Hu/p/10715682.html

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的[JDK8]性能优化之使用LongAdder替换AtomicLong的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。