前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Java并发包下Atomic相关类的使用

Java并发包下Atomic相关类的使用

作者头像
程序猿川子
发布于 2025-05-12 10:00:39
发布于 2025-05-12 10:00:39
3000
代码可运行
举报
运行总次数:0
代码可运行

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,并且只能使用一次

使用示例
  1. 基本类型原子类,以AtomicInteger为例

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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();
    }
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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));
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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();
    }

}

输出结果

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 体验AI代码助手 代码解读复制代码t1 come in
t1 获取锁成功
t2 come in
t1 释放锁
t2 获取锁成功
t2 释放锁

AtomicIntegerFieldUpdater使用示例

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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:只能用来计算加法,且从零开始计算

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ini 体验AI代码助手 代码解读复制代码LongAdder longAdder = new LongAdder();
longAdder.increment();
longAdder.increment();
longAdder.increment();
// 输出3
System.out.println(longAdder.longValue());

LongAccumulator:提供了自定义的函数操作

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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万次,最后输出结果(类似高并发点赞功能)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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性能明显高于其它的

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
arduino 体验AI代码助手 代码解读复制代码synchronized 耗时 941 毫秒 50000000
AtomicInteger 耗时 980 毫秒 50000000
AtomicLong 耗时 984 毫秒 50000000
LongAdder 耗时 153 毫秒 50000000
LongAccumulator 耗时 262 毫秒 50000000

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
java高并发系列 - 第32天:高并发中计数器的实现方式有哪些?
我们使用4种方式实现,看一下其性能,然后引出为什么需要使用LongAdder、LongAccumulator。
路人甲Java
2019/12/10
1.8K0
java高并发系列 - 第32天:高并发中计数器的实现方式有哪些?
原子操作类Atomic
因为对象的属性修改类型原子类都是抽象类,所以每次使用都必须使用静态方法newUpdater()创建一个更新器,并且需要设置想要更新的类和属性。
鱼找水需要时间
2023/02/16
2.5K0
原子操作类Atomic
原子操作类解读
Java中提供了一些原子操作类,用于实现多线程环境下的数据同步问题。其中最常见的有以下几种:
一个风轻云淡
2023/10/15
2750
原子操作类解读
《Java面试题集中营》- Java并发
Jdk提供了stop()方法用于强制停止线程,但官方并不建议使用,因为强制停止线程会导致线程使用的资源,比如文件描述符、网络连接处于不正常的状态。建议使用标志位的方式来终止线程,如果线程中有使用无限期的阻塞方式,比如wait()没有设置超时时间,就只能使用interrupt()方法来终止线程
阿提说说
2024/07/14
1120
java高并发系列 - 第23天:JUC中原子类,一篇就够了
JUC中的原子类都是都是依靠volatile、CAS、Unsafe类配合来实现的,需要了解的请移步: volatile与Java内存模型 java中的CAS JUC底层工具类Unsafe
路人甲Java
2019/12/10
5030
java高并发系列 - 第23天:JUC中原子类,一篇就够了
并发编程中的原子类
对多线程访问同一个变量,我们需要加锁,而锁是比较消耗性能的,JDk1.5之后, 新增的原子操作类提供了 一种用法简单、性能高效、线程安全地更新一个变量的方式, 这些类同样位于JUC包下的atomic包下,发展 到JDk1.8,该包下共有17个类, 囊括了原子更新基本类型、原子更新数组、原子更新属性、原子更新引用
Dream城堡
2019/05/20
5000
一篇文章快速搞懂 Atomic(原子整数/原子引用/原子数组/LongAdder)
相信大部分开发人员,或多或少都看过或写过并发编程的代码。并发关键字除了Synchronized(如有不懂请移至传送门,[万字长文,建议收藏]关于Synchronized锁升级,你该了解这些  ),还有另一大分支Atomic。如果大家没听过没用过先看基础篇,如果听过用过,请滑至底部看进阶篇,深入源码分析。
陈琛
2020/06/17
1.3K0
一篇文章快速搞懂 Atomic(原子整数/原子引用/原子数组/LongAdder)
Java线程安全如何进行原子操作,一致性的最佳实践
1.它可以延迟流水线执行指令(de-pipeline),使CPU不会消耗过多的执行资源,延迟的时间取决于具体实现的版本,在一些处理器上延迟时间是零。 2.它可以避免在退出循环的时候因内存顺序冲突(Memory Order Violation)而引起CPU流水线被清空(CPU Pipeline Flush),从而提高CPU的执行效率。
IT架构圈
2020/07/21
6960
Java线程安全如何进行原子操作,一致性的最佳实践
自增效率比较
【参考】volatile 解决多线程内存不可见问题。对于一写多读,是可以解决变量同步问题,但是如果多写,同样无法解决线程安全问题。 说明:如果是 count++操作,使用如下类实现:AtomicInteger count = new AtomicInteger(); count.addAndGet(1); 如果是 JDK8,推荐使用 LongAdder 对象,比 AtomicLong 性能更好(减少乐观锁的重试次数)。
九转成圣
2024/04/10
940
吃透并发编程之—-Atomic原子类学习思考
发生冲突的情况会大大增加 (也就是存在大量更新时去比较预期的值发生了变化,导致此次更新失效的情况),因此效率会大大降低
Joseph_青椒
2023/09/07
2750
吃透并发编程之—-Atomic原子类学习思考
【死磕Java并发】常用并发原子类详解
在 Java 的java.util.concurrent包中,除了提供底层锁、并发同步等工具类以外,还提供了一组原子操作类,大多以Atomic开头,他们位于java.util.concurrent.atomic包下。
Java极客技术
2023/12/14
3310
【死磕Java并发】常用并发原子类详解
多线程编程学习八(原子操作类).
Java 在 JDK 1.5 中提供了 java.util.concurrent.atomic 包,这个包中的原子操作类提供了一种用法简单、性能高效、线程安全地更新一个变量的方式。主要提供了四种类型的原子更新方式,分别是原子更新基本类型、原子更新数组、原子更新引用和原子更新属性。
JMCui
2019/09/09
3120
多线程编程学习八(原子操作类).
Java并发——CAS(十)
在大多数处理器的指令中,都会实现 CAS 相关的指令,这一条指令就可以完成“比较并交换”的操作,也正是由于这是一条(而不是多条)CPU 指令,所以 CAS 相关的指令是具备原子性的,这个组合操作在执行期间不会被打断,这样就能保证并发安全。由于这个原子性是由 CPU 保证的,所以无需我们程序员来操心。
翰墨飘香
2024/05/21
2950
死磕 java原子类之终结篇
原子操作是指不会被线程调度机制打断的操作,这种操作一旦开始,就一直运行到结束,中间不会有任何线程上下文切换。
彤哥
2019/07/08
4780
死磕 java原子类之终结篇
005. 线程安全之原子操作
局部对象引用本身不共享,但是引用的对象存储在共享堆中。如果方法内创建的对象,只有在方法中传递,并且不对其他线程可用,那么也是线程安全的。
山海散人
2021/03/03
2520
005. 线程安全之原子操作
彻底理解Java并发:Java并发原子类
在 Jdk1.5 开始 Java 开始引进提供了 java.util.concurrent.atomic 包,到 Jdk8 时,atomic 包共提供了 16 个原子类,分为 6 种类型,分别是:①、基本类型原子类;②、数组类型原子类;③、引用类型原子类;④、原子更新属性;⑤、Adder 加法器;⑥、积累器。
栗筝i
2022/12/01
6450
你还只会用 AtomicXXX ?!恭喜你,可以下岗了!
在之前的文章中,栈长介绍了 LongAdder 的使用,性能实在太炸了,你还在用 AtomicInteger、AtomicLong 吗?如果你还不知道 LongAdder,赶紧看我之前写的那篇文章。
Java技术栈
2022/12/17
2810
你还只会用 AtomicXXX ?!恭喜你,可以下岗了!
JDK8并发编程实战源码探究系列(一)并发包概览
一线大厂招聘,高并发系统研发,进阶高级程序员…并发编程是必须掌握的技能。而深究其原理、源码才能写出高质量的代码。 JDK8并发编程实战源码探究系列涉及java.util.concurrent 包几乎所有类或者接口的原理、使用实战、源码讲解。 中间可能还会穿插计算机原理底层、CPU、操作系统、JMM、字节码分析等知识点,更深刻、全方位掌握并发编程。
青山师
2023/05/05
1390
并发编程系列之掌握原子类使用
如果不加锁,仅仅使用volatile关键字?运行几次,发现统计的数值是有偏差的,所以volatile是不一定能保证线程安全的
SmileNicky
2021/12/06
2230
并发编程系列之掌握原子类使用
Java16个原子类介绍-基于JDK8
emmmm,在写文章前我也翻阅了好多资料和书籍,其实大家在对原子类方法的使用介绍基本都没问题,但是对于java中原子类的个数是五花八门,下面我就把自己都认知和书籍资料结合起来给大家简单都介绍下java中原子类的应用。
胖虎
2019/06/26
8440
Java16个原子类介绍-基于JDK8
相关推荐
java高并发系列 - 第32天:高并发中计数器的实现方式有哪些?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验