package thread;
import java.lang.reflect.Field;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.LongAdder;
import sun.misc.Unsafe;
@SuppressWarnings("restriction")
public class Sy2 {
// 测试规模,调用一次getAndIncreaseX视作提供一次业务服务,记录提供TEST_SIZE次服务的耗时
private static final int TEST_SIZE = 100000000;
// 客户线程数
private static final int THREAD_COUNT = 10;
// 使用CountDownLatch让各线程同时开始
private CountDownLatch cdl = new CountDownLatch(THREAD_COUNT + 1);
private int n = 0;
private AtomicInteger ai = new AtomicInteger(0);
private static LongAdder longAdder = new LongAdder();
private long startTime;
private static volatile int value = 0;
private static long casOffset;
public static Unsafe unsafe;
static {
try {
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
unsafe = (Unsafe) theUnsafe.get(null); // initial unsafe
// get field offset by unsafe
casOffset = unsafe.staticFieldOffset(Sy2.class.getDeclaredField("value"));
} catch (Exception e) {
e.printStackTrace();
}
}
public void init() {
startTime = System.nanoTime();
}
public int cas() {
while (true) {
if (unsafe.compareAndSwapInt(Sy2.class, casOffset, value, value + 1))
return value;
}
}
/**
* 使用AtomicInteger.getAndIncrement,测试结果为1.8比1.7有明显性能提升
*
* @return
*/
private final int getAndIncreaseA() {
int result = ai.getAndIncrement();
if (result == TEST_SIZE) {
System.out.println(System.nanoTime() - startTime);
System.exit(0);
}
return result;
}
/**
* 使用synchronized来完成同步,测试结果为1.7和1.8几乎无性能差别
*
* @return
*/
private final int getAndIncreaseB() {
int result;
synchronized (this) {
result = n++;
}
if (result == TEST_SIZE) {
System.out.println(System.nanoTime() - startTime);
System.exit(0);
}
return result;
}
/**
* 使用AtomicInteger.compareAndSet在java代码层面做失败重试(与1.7的AtomicInteger.getAndIncrement的实现类似),
* 测试结果为1.7和1.8几乎无性能差别
*
* @return
*/
private final int getAndIncreaseC() {
int result;
do {
result = ai.get();
} while (!ai.compareAndSet(result, result + 1));
if (result == TEST_SIZE) {
System.out.println(System.nanoTime() - startTime);
System.exit(0);
}
return value;
}
/**
* 自己调用 unsafe.compareAndSwapInt
*/
private void getAndIncreaseD() {
int result = cas();
if (result == TEST_SIZE) {
System.out.println(System.nanoTime() - startTime);
System.exit(0);
}
}
/**
* long adder
*/
private void getAndIncreaseE() {
longAdder.increment();
if(longAdder.sum() == TEST_SIZE) {
System.out.println(System.nanoTime() - startTime);
System.exit(0);
}
}
public class MyTask implements Runnable {
@Override
public void run() {
cdl.countDown();
try {
cdl.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
while (true)
getAndIncreaseE();// getAndIncreaseB();
}
}
public static void main(String[] args) throws InterruptedException {
Sy2 at = new Sy2();
for (int n = 0; n < THREAD_COUNT; n++)
new Thread(at.new MyTask()).start();
System.out.println("start");
at.init();
at.cdl.countDown();
}
}
result (可能 根据电脑当前资源,时间有一些差异):
getAndIncreaseA --> 2146580139
getAndIncreaseB --> 4189839441
getAndIncreaseC --> 9497379502
getAndIncreaseD --> 8152335259
getAndIncreaseE --> 2326690013
java 1.8 之后的版本 AtomicInteger.getAndIncrement 在并发冲突严重时,性能有很大提升。
LongAdder 如果不频繁调用sum()函数,increment() 函数是最快的,因为内部的的加法操作时,是通过分配一个数组,hash散列 每个线程ID,最后求和各个数组的组,典型的空间换时间的操作。
当 TEST_SIZE > 10000000 时候的并发,longadder 显著高于 AtomicInteger.getAndIncrement
网友评论