36.基于CAS实现的java类

JUC, java.util.concurrent并发工具包下。

1.原子整数

AtomicInteger

AtomicLong

AtomicBoolean

底层用的CAS来实现。

AtomicInteger类的incrementAndGet方法,addAndGet方法

java 复制代码
public static void main(String[] args) {
        AtomicInteger atomicInteger = new AtomicInteger();
        int i = atomicInteger.incrementAndGet(); //i++
        log.info("i=={}", i);
        //这里返回的是1,但是atomicInteger中的值已经变成2了
        int j = atomicInteger.getAndIncrement();//++i
        log.info("j=={}", j);
        log.info("value=={}", atomicInteger.get());

        //先返回原来的值
        int andAdd = atomicInteger.getAndAdd(2);
        log.info("andAdd={}", andAdd);
        //返回加运算之后的值
        int i1 = atomicInteger.addAndGet(3);
        log.info("i1=={}", i1);

    }
复制代码
int andAdd = atomicInteger.getAndAdd(-1 * 2); //减法

AtomicInteger类的updateAndGet方法的原理分析:

复制代码
public final int updateAndGet(IntUnaryOperator updateFunction) {
    int prev, next;
    do {
        prev = get();
        next = updateFunction.applyAsInt(prev);
    } while (!compareAndSet(prev, next));
    return next;
}

IntUnaryOperator这个接口中定义了方法 int applyAsInt(int prev),所以调用者只需要传入applyAsInt方法的实现逻辑即可。

复制代码
AtomicInteger atomicInteger = new AtomicInteger(5);
//**乘法
int i2 = atomicInteger.updateAndGet(e -> e * 10);
log.info("i2=={}", i2);

2.原子引用类型

AtomicReference

AtomicMarkableReference

AtomicStampedReference

java 复制代码
public class AccountDemo {
    public static void main(String[] args) {
        BigdecimalAccountCAS bigdecimalAccountCAS = new BigdecimalAccountCAS(new BigDecimal("10000"));
        BigDecimalAccount.demo(bigdecimalAccountCAS);
    }
}

class BigdecimalAccountCAS implements BigDecimalAccount{

    private AtomicReference<BigDecimal> balance;

    public BigdecimalAccountCAS (BigDecimal balance) {
        this.balance = new AtomicReference<>(balance);
    }

    @Override
    public BigDecimal getBalance() {
        return this.balance.get();
    }

    @Override
    public void withDraw(BigDecimal amont) {
        while(true) {
            BigDecimal prev = balance.get();
            BigDecimal subtract = prev.subtract(amont);
            if (balance.compareAndSet(prev, subtract)) {
                break;
            }
        }
//        this.balance.updateAndGet(e -> e.subtract(amont));
    }
}


interface BigDecimalAccount {

    //获取余额
    BigDecimal getBalance();

    //取款
    void withDraw(BigDecimal amont);

    static void demo(BigDecimalAccount account) {
        //定义一个线程集合
        List<Thread> ts = new ArrayList<>();
        long start = System.nanoTime();
        //创建一千个线程,每个线程取出10元
        for (int i = 0; i < 1000; i++) {
            ts.add(new Thread(() -> account.withDraw(BigDecimal.TEN)));
        }
        //启动每一个线程
        ts.forEach( e -> e.start());
        //等所有线程执行完毕
        ts.forEach( e -> {
            try {
                e.join();
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
        });
        long duration = System.nanoTime() - start;
        System.out.println("花费时长:"+duration);
        System.out.println("余额:"+ account.getBalance());
    }
}
相关推荐
学长毕业设计2 小时前
基于SpringBoot的公益基金管理系统(源码+文档+讲解视频)
java·spring boot·后端
东小西2 小时前
【SAA实战】第 3 篇 · 工具调用全攻略:把业务能力交给 Agent 自己调度
java·后端·spring
东小西2 小时前
【SAA实战】第 4 篇 · Agent 短期记忆:saver 让 Agent 跨轮记得住(threadId 隔离)
java·后端·spring
许彰午2 小时前
22-DataCenter报文序列化
java·低代码·架构·状态模式
2601_962065253 小时前
[MySQL] SQL优化之性能分析
java·sql·mysql
小范同学_3 小时前
JDK1.7 与 JDK1.8 HashMap 底层原理对比 + 数组并发扩容死循环详解
java·开发语言
予昊4 小时前
从零实现“在线五子棋对战“:WebSocket 实时通信 + 段位匹配
java·开发语言·网络·websocket
2601_962203514 小时前
【SpringAI入门】初识SpringAI
java
weixin_461408584 小时前
Mybatis-flex小记
java·开发语言·mybatis
2601_962177135 小时前
【MySQL篇】聚合查询,联合查询
android·java·mysql