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());
    }
}
相关推荐
卡尔特斯4 小时前
Android Kotlin 项目代理配置【详细步骤(可选)】
android·java·kotlin
白鲸开源4 小时前
Ubuntu 22 下 DolphinScheduler 3.x 伪集群部署实录
java·ubuntu·开源
ytadpole4 小时前
Java 25 新特性 更简洁、更高效、更现代
java·后端
纪莫5 小时前
A公司一面:类加载的过程是怎么样的? 双亲委派的优点和缺点? 产生fullGC的情况有哪些? spring的动态代理有哪些?区别是什么? 如何排查CPU使用率过高?
java·java面试⑧股
JavaGuide5 小时前
JDK 25(长期支持版) 发布,新特性解读!
java·后端
用户3721574261355 小时前
Java 轻松批量替换 Word 文档文字内容
java
白鲸开源5 小时前
教你数分钟内创建并运行一个 DolphinScheduler Workflow!
java
Java中文社群6 小时前
有点意思!Java8后最有用新特性排行榜!
java·后端·面试
代码匠心6 小时前
从零开始学Flink:数据源
java·大数据·后端·flink
间彧6 小时前
Spring Boot项目中如何自定义线程池
java