重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
1、AtomicLong是利用了底层的CAS操作来提供并发性。
2、在并发量较低的环境下,线程冲突的概率比较小,自旋的次数不会很多。但是,高并发环境下,N个线程同时进行自旋操作,会出现大量失败并不断自旋的情况,此时AtomicLong的自旋会成为瓶颈。
3、AtomicLong中有个内部volatile变量value保存着实际的long值,所有的操作都是针对该变量进行。也就是说,高并发环境下,value变量其实是一个热点,也就是N个线程竞争一个热点。
创新互联主营永城网站建设的网络公司,主营网站建设方案,成都App定制开发,永城h5成都微信小程序搭建,永城网站营销推广欢迎永城等地区企业咨询
1、LongAdder的基本思路就是分散热点,将value值分散到一个数组中,不同线程会命中到数组的不同槽中,各个线程只对自己槽中的那个值进行CAS操作,这样热点就被分散了,冲突的概率就小很多。如果要获取真正的long值,只要将各个槽中的变量值累加返回。
2、低并发、一般的业务场景下AtomicLong是足够了。如果并发量很多,存在大量写多读少的情况,那LongAdder可能更合适。
1、创建一个Maven工程,Pom.xml代码如下
4.0.0
com.jane
jmh2
1.0-SNAPSHOT
org.openjdk.jmh
jmh-core
1.20
org.openjdk.jmh
jmh-generator-annprocess
1.20
org.codehaus.mojo
exec-maven-plugin
run-benchmarks
integration-test
exec
test
java
-classpath
org.openjdk.jmh.Main
.*
2、启动文件
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();
}
}
3、单线程下的性能对比
吞吐量:AtomicLong性能更好
平均消耗时间:AtomicLong耗时更小
4、20个线程下的性能对比
吞吐量:LongAdder优势明显
平均消耗时间:LongAdder优势明显