java.util.concurrent.atomic 分类:
- 基本类型原子类
- AtomicInteger
- AtomicLong
- AtomicBoolean
- 数组类型原子类
- AtomicIntegerArray
- AtomicLongArray
- AtomicReferenceArray
- 引用类型原子类
- AtomicReference
- AtomicMarkableReference
- AtomicStampedReference
- 对象的属性修改原子类
- AtomicIntegerFieldUpdater
- AtomicLongFieldUpdater
- AtomicReferenceFieldUpdater
- 原子操作增强类
- DoubleAccumulator
- DoubleAdder
- LongAccumulator
- LongAdder
AtomicStampedReference 和 AtomicMarkableReference 区别
AtomicStampedReference是携带版本号的引用类型原子类,可以解决ABA问题,记录的是修改过几次
AtomicMarkableReference是将AtomicStampedReference的版本号,简化为true或false,并且只能使用一次
使用示例
- 基本类型原子类,以AtomicInteger为例
java
体验AI代码助手
代码解读
复制代码
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicTest {
/**
* 50个线程
*/
private static final int THREAD_NUM = 50;
private static final CountDownLatch countDownLatch = new CountDownLatch(THREAD_NUM);
public static void main(String[] args) throws InterruptedException {
MyNumber myNumber = new MyNumber();
for (int i = 0; i < THREAD_NUM; i++) {
new Thread(() -> {
try {
for (int j = 0; j < 1000; j++) {
myNumber.add();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
countDownLatch.countDown();
}
}).start();
}
countDownLatch.await();
System.out.println("最终结果:" + myNumber.num.get());
}
}
class MyNumber {
AtomicInteger num = new AtomicInteger();
public void add() {
num.getAndIncrement();
}
}
- 数组类型原子类,以AtomicIntegerArray为例
csharp
体验AI代码助手
代码解读
复制代码
public static void main(String[] args) {
AtomicIntegerArray atomicIntegerArray1 = new AtomicIntegerArray(5);
AtomicIntegerArray atomicIntegerArray2 = new AtomicIntegerArray(new int[5]);
AtomicIntegerArray atomicIntegerArray3 = new AtomicIntegerArray(new int[]{1, 2, 3, 4, 5});
for (int i = 0; i < atomicIntegerArray3.length(); i++) {
// 输出 1、2、3、4、5
System.out.println(atomicIntegerArray3.get(i));
}
int temp = 0;
atomicIntegerArray3.getAndSet(0, 111);
// 输出 111
System.out.println(atomicIntegerArray3.get(0));
// +1
atomicIntegerArray3.getAndIncrement(1);
// +1
atomicIntegerArray3.getAndIncrement(1);
// 输出 4
System.out.println(atomicIntegerArray3.get(1));
}
- 引用类型原子类,以AtomicReference为例实现一个自旋锁
java
体验AI代码助手
代码解读
复制代码
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
public class SpinLockDemo {
AtomicReference<Thread> atomicReference = new AtomicReference<>();
public void MyLock() {
System.out.println(Thread.currentThread().getName() + " come in");
while (!atomicReference.compareAndSet(null, Thread.currentThread())) {
}
System.out.println(Thread.currentThread().getName() + " 获取锁成功");
}
public void MyUnLock() {
while (!atomicReference.compareAndSet(Thread.currentThread(), null)) {
}
System.out.println(Thread.currentThread().getName() + " 释放锁");
}
public static void main(String[] args) {
SpinLockDemo spinLockDemo = new SpinLockDemo();
new Thread(() -> {
// 获取锁
spinLockDemo.MyLock();
try {
// 拿到锁使用3秒钟
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 释放锁
spinLockDemo.MyUnLock();
}, "t1").start();
new Thread(() -> {
spinLockDemo.MyLock();
spinLockDemo.MyUnLock();
}, "t2").start();
}
}
输出结果
体验AI代码助手
代码解读
复制代码
t1 come in
t1 获取锁成功
t2 come in
t1 释放锁
t2 获取锁成功
t2 释放锁
- 对象的属性修改原子类,是以一种线程安全的方式操作非线程安全对象内的某些字段
- 使用要求:更新的对象属性必须使用 public volatile 进行修饰
AtomicIntegerFieldUpdater使用示例
java
体验AI代码助手
代码解读
复制代码
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
public class AtomicIntegerFieldUpdaterDemo {
public static void main(String[] args) throws InterruptedException {
BankAccount bankAccount = new BankAccount();
for (int i = 0; i < 1000; i++) {
new Thread(() -> {
bankAccount.doAction(bankAccount);
}).start();
}
TimeUnit.SECONDS.sleep(1);
// 输出1000
System.out.println(bankAccount.money);
}
}
class BankAccount {
public String bankName = "中国银行";
public volatile int money;
// 通过反射获取对象
AtomicIntegerFieldUpdater<BankAccount> updater = AtomicIntegerFieldUpdater.newUpdater(BankAccount.class, "money");
public void doAction(BankAccount bankAccount) {
updater.incrementAndGet(bankAccount);
}
}
- 原子操作增强类
LongAdder:只能用来计算加法,且从零开始计算
ini
体验AI代码助手
代码解读
复制代码
LongAdder longAdder = new LongAdder();
longAdder.increment();
longAdder.increment();
longAdder.increment();
// 输出3
System.out.println(longAdder.longValue());
LongAccumulator:提供了自定义的函数操作
ini
体验AI代码助手
代码解读
复制代码
LongAccumulator longAccumulator = new LongAccumulator((x, y) -> x + y, 0);
longAccumulator.accumulate(1);
longAccumulator.accumulate(2);
longAccumulator.accumulate(3);
// 输出6
System.out.println(longAccumulator.longValue());
Atomic高性能对比
示例:使用50个线程,每个线程累加100万次,最后输出结果(类似高并发点赞功能)
ini
体验AI代码助手
代码解读
复制代码
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAccumulator;
import java.util.concurrent.atomic.LongAdder;
class ClickNumber {
int number = 0;
public synchronized void addBySynchronized() {
number++;
}
AtomicInteger atomicInteger = new AtomicInteger(0);
public void addByAtomicInteger() {
atomicInteger.incrementAndGet();
}
AtomicLong atomicLong = new AtomicLong(0);
public void addByAtomicLong() {
atomicLong.incrementAndGet();
}
LongAdder longAdder = new LongAdder();
public void addByLongAdder() {
longAdder.increment();
}
LongAccumulator longAccumulator = new LongAccumulator(Long::sum, 0);
public void addByLongAccumulator() {
longAccumulator.accumulate(1);
}
}
public class LongAdderDemo {
public static void main(String[] args) throws InterruptedException {
ClickNumber clickNumber = new ClickNumber();
long startTime;
long endTime;
CountDownLatch countDownLatch1 = new CountDownLatch(50);
CountDownLatch countDownLatch2 = new CountDownLatch(50);
CountDownLatch countDownLatch3 = new CountDownLatch(50);
CountDownLatch countDownLatch4 = new CountDownLatch(50);
CountDownLatch countDownLatch5 = new CountDownLatch(50);
startTime = System.currentTimeMillis();
// 50个线程
for (int i = 1; i <= 50; i++) {
new Thread(() -> {
try {
for (int j = 1; j <= 1000000; j++) {
// 每个线程累加100万次
clickNumber.addBySynchronized();
}
} finally {
countDownLatch1.countDown();
}
}, String.valueOf(i)).start();
}
countDownLatch1.await();
endTime = System.currentTimeMillis();
System.out.println("synchronized 耗时 " + (endTime - startTime) + " 毫秒 " + clickNumber.number);
startTime = System.currentTimeMillis();
for (int i = 1; i <= 50; i++) {
new Thread(() -> {
try {
for (int j = 1; j <= 1000000; j++) {
clickNumber.addByAtomicInteger();
}
} finally {
countDownLatch2.countDown();
}
}, String.valueOf(i)).start();
}
countDownLatch2.await();
endTime = System.currentTimeMillis();
System.out.println("AtomicInteger 耗时 " + (endTime - startTime) + " 毫秒 " + clickNumber.atomicInteger.get());
startTime = System.currentTimeMillis();
for (int i = 1; i <= 50; i++) {
new Thread(() -> {
try {
for (int j = 1; j <= 1000000; j++) {
clickNumber.addByAtomicLong();
}
} finally {
countDownLatch3.countDown();
}
}, String.valueOf(i)).start();
}
countDownLatch3.await();
endTime = System.currentTimeMillis();
System.out.println("AtomicLong 耗时 " + (endTime - startTime) + " 毫秒 " + clickNumber.atomicLong.get());
startTime = System.currentTimeMillis();
for (int i = 1; i <= 50; i++) {
new Thread(() -> {
try {
for (int j = 1; j <= 1000000; j++) {
clickNumber.addByLongAdder();
}
} finally {
countDownLatch4.countDown();
}
}, String.valueOf(i)).start();
}
countDownLatch4.await();
endTime = System.currentTimeMillis();
System.out.println("LongAdder 耗时 " + (endTime - startTime) + " 毫秒 " + clickNumber.longAdder.longValue());
startTime = System.currentTimeMillis();
for (int i = 1; i <= 50; i++) {
new Thread(() -> {
try {
for (int j = 1; j <= 1000000; j++) {
clickNumber.addByLongAccumulator();
}
} finally {
countDownLatch5.countDown();
}
}, String.valueOf(i)).start();
}
countDownLatch5.await();
endTime = System.currentTimeMillis();
System.out.println("LongAccumulator 耗时 " + (endTime - startTime) + " 毫秒 " + clickNumber.longAccumulator.longValue());
}
}
从输出结果可见,LongAdder性能明显高于其它的
arduino
体验AI代码助手
代码解读
复制代码
synchronized 耗时 941 毫秒 50000000
AtomicInteger 耗时 980 毫秒 50000000
AtomicLong 耗时 984 毫秒 50000000
LongAdder 耗时 153 毫秒 50000000
LongAccumulator 耗时 262 毫秒 50000000