JMH測試AtomicLong和LongAdder的性能

AtomicLong 和 LongAdder 的區別

AtomicLong

一、AtomicLong是利用了底層的CAS操做來提供併發性。
二、在併發量較低的環境下,線程衝突的機率比較小,自旋的次數不會不少。可是,高併發環境下,N個線程同時進行自旋操做,會出現大量失敗並不斷自旋的狀況,此時AtomicLong的自旋會成爲瓶頸。
三、AtomicLong中有個內部volatile變量value保存着實際的long值,全部的操做都是針對該變量進行。也就是說,高併發環境下,value變量實際上是一個熱點,也就是N個線程競爭一個熱點。java

LongAdder

一、LongAdder的基本思路就是分散熱點,將value值分散到一個數組中,不一樣線程會命中到數組的不一樣槽中,各個線程只對本身槽中的那個值進行CAS操做,這樣熱點就被分散了,衝突的機率就小不少。若是要獲取真正的long值,只要將各個槽中的變量值累加返回。
二、低併發、通常的業務場景下AtomicLong是足夠了。若是併發量不少,存在大量寫多讀少的狀況,那LongAdder可能更合適。apache

利用JMH測試AtomicLong和LongAdder的性能

一、建立一個Maven工程,Pom.xml代碼以下數組

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jane</groupId>
    <artifactId>jmh1</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!-- JMH -->
        <dependency>
            <groupId>org.openjdk.jmh</groupId>
            <artifactId>jmh-core</artifactId>
            <version>1.20</version>
        </dependency>
        <dependency>
            <groupId>org.openjdk.jmh</groupId>
            <artifactId>jmh-generator-annprocess</artifactId>
            <version>1.20</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <id>run-benchmarks</id>
                        <phase>integration-test</phase>
                        <goals>
                            <goal>exec</goal>
                        </goals>
                        <configuration>
                            <classpathScope>test</classpathScope>
                            <executable>java</executable>
                            <arguments>
                                <argument>-classpath</argument>
                                <classpath />
                                <argument>org.openjdk.jmh.Main</argument>
                                <argument>.*</argument>
                            </arguments>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

二、啓動文件併發

package com.jane;

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;

@BenchmarkMode(Mode.AverageTime) // 測試方法平均執行時間,若是測試吞入量則換成Mode.Throughput
@OutputTimeUnit(TimeUnit.MICROSECONDS) // 輸出結果的時間粒度爲微秒
public class Main {
    private static AtomicLong count = new AtomicLong();
    private static LongAdder longAdder = new LongAdder();

    @Benchmark
    @Threads(1) //單位時間內也,默認一秒啓動多少個線程進行測試
    public void atolong(){
        count.getAndIncrement(); //測試AtomicLong遞增方法
    }

    @Benchmark
    @Threads(1) //單位時間內也,默認一秒啓動多少個線程進行測試
    public void loadder(){
        longAdder.increment();//測試LongAdder的遞增方法
    }

    public static void main(String[] args) throws RunnerException {
        Options options = new OptionsBuilder()
                .include(Main.class.getSimpleName())
                .forks(1)
                .build();
        new Runner(options).run();
    }
}

三、單線程下的性能對比maven

JMH測試AtomicLong和LongAdder的性能

吞吐量:AtomicLong性能更好ide

JMH測試AtomicLong和LongAdder的性能

平均消耗時間:AtomicLong耗時更小高併發

JMH測試AtomicLong和LongAdder的性能

四、20個線程下的性能對比性能

JMH測試AtomicLong和LongAdder的性能

吞吐量:LongAdder優點明顯測試

JMH測試AtomicLong和LongAdder的性能

平均消耗時間:LongAdder優點明顯ui

JMH測試AtomicLong和LongAdder的性能

相關文章
相關標籤/搜索