AtomicInteger 类底层存储一个int值,并提供方法对该int值进行原子操作。AtomicInteger 作为java.util.concurrent.atomic包的一部分,从Java 1.5开始引入。

1. AtomicInteger基础用法

通过下文的AtomicInteger构造方法,可以创建一个AtomicInteger对象,该对象的初始值默认为0。AtomicInteger提供get和set方法,获取底层int整数值,与设置int整数值

//初始值为0的atomicInteger对象
AtomicInteger atomicInteger = new AtomicInteger(); //初始值为200的atomicInteger对象
AtomicInteger atomicInteger = new AtomicInteger(200); int currentValue = atomicInteger.get(); //100
atomicInteger.set(2453); //现在的值是 2453

但是上面的方法,对于AtomicInteger而言并不是它的核心内容,AtomicInteger核心内容体现在它的原子性,我们下文介绍。

2. 什么时候需要使用AtomicInteger

我们通常在以下的两种场景下使用AtomicInteger

  1. 多线程并发场景下操作一个计数器,需要保证计数器操作的原子性。
  2. 进行数值比较,如果给定值与当前值相等,进行数值的更新操作,并实现操作的非阻塞算法。

2.1. 原子计数器场景

把AtomicInteger作为一个计数器使用,AtomicInteger提供了若干方法进行加法、减法的原子操作。

比如从一个map里面获取值,用get()方法,这是第一个操作;获取到值之后给这个值加上n,这是第二个操作;将进行过加法运算的值,再次放入map里面是第三个操作。所谓操作的原子性是指:在多线程并发的场景下,上面的三个操作是原子性的,也就是不可分割的。不会出现A线程get了数值,B线程同时也get到了该数值,两个线程同时为该值做运算并先后再次放入的情况,这种情况对于AtomicInteger而言是不会出现的,AtomicInteger操作是线程安全的、不可分割的。

  • addAndGet()- 将给定的值加到当前值上,并在加法后返回新值,并保证操作的原子性。
  • getAndAdd()- 将给定的值加到当前值上,并返回旧值,并保证操作的原子性。
  • incrementAndGet()- 将当前值增加1,并在增加后返回新值。它相当于++i操作,并保证操作的原子性。
  • getAndIncrement()- 将当前值增加1并返回旧值。相当于++i操作,并保证操作的原子性。
  • decrementAndGet()- 将当前值减去1,并在减去后返回新值,相当于i--操作,并保证操作的原子性。
  • getAndDecrement()- 将当前值减去1,并返回旧值。它相当于 --i操作,并保证操作的原子性。

下面是AtomicInteger原子性操作方法的例子

public class Main {
public static void main(String[] args) {
//初始值为100的atomic Integer
AtomicInteger atomicInteger = new AtomicInteger(100); System.out.println(atomicInteger.addAndGet(2)); //加2并返回102
System.out.println(atomicInteger); //102 System.out.println(atomicInteger.getAndAdd(2)); //先获取102,再加2
System.out.println(atomicInteger); //104 System.out.println(atomicInteger.incrementAndGet()); //加1再获取105
System.out.println(atomicInteger); //105 System.out.println(atomicInteger.getAndIncrement()); //先获取105再加1
System.out.println(atomicInteger); //106 System.out.println(atomicInteger.decrementAndGet()); //减1再获取105
System.out.println(atomicInteger); //105 System.out.println(atomicInteger.getAndDecrement()); //先获取105,再减1
System.out.println(atomicInteger); //104
}
}

2.2. 数值比对及交换操作

compareAndSet操作将一个内存位置的内容与一个给定的值进行比较,只有当它们相同时,才会将该内存位置的内容修改为一个给定的新值。这个过程是以单个原子操作的方式完成的。

compareAndSet方法:如果当前值==预期值,则将值设置为给定的更新值。

boolean compareAndSet(int expect, int update)
  • expect是预期值
  • update是更新值

AtomicInteger compareAndSet() 方法的例子

import java.util.concurrent.atomic.AtomicInteger;

public class Main {
public static void main(String[] args) {
//初始值为100的atomic Integer
AtomicInteger atomicInteger = new AtomicInteger(100); //当前值100 = 预期值100,所以设置atomicInteger=110
boolean isSuccess = atomicInteger.compareAndSet(100,110);
System.out.println(isSuccess); //输出结果为true表示操作成功 //当前值110 = 预期值100?不相等,所以atomicInteger仍然等于110
isSuccess = atomicInteger.compareAndSet(100,120);
System.out.println(isSuccess); //输出结果为false表示操作失败
}
}

3. 总结

AtomicInteger可以帮助我们在不使用synchronized同步锁的情况下,实现在多线程场景下int数值操作的线程安全,操作的原子性。并且使用AtomicInteger来实现int数值的原子操作,远比使用synchronized同步锁效率更高。

java.util.concurrent.atomic包不仅为我们提供了AtomicInteger,还提供了AtomicBoolean布尔原子操作类、AtomicLong长整型布尔原子操作类、AtomicReference对象原子操作类、AtomicIntegerArray整型数组原子操作类、AtomicLongArray长整型数组原子操作类、AtomicReferenceArray对象数组原子操作类。

欢迎关注我的博客,里面有很多精品合集

  • 本文转载注明出处(必须带连接,不能只转文字):字母哥博客。

觉得对您有帮助的话,帮我点赞、分享!您的支持是我不竭的创作动力! 。另外,笔者最近一段时间输出了如下的精品内容,期待您的关注。

java并发编程JUC第十二篇:AtomicInteger原子整型的更多相关文章

  1. java并发编程JUC第十篇:CyclicBarrier线程同步

    在之前的文章中已经为大家介绍了java并发编程的工具:BlockingQueue接口.ArrayBlockingQueue.DelayQueue.LinkedBlockingQueue.Priorit ...

  2. Java并发编程系列之三十二:丢失的信号

    这里的丢失的信号是指线程必须等待一个已经为真的条件,在開始等待之前没有检查等待条件.这样的场景事实上挺好理解,假设一边烧水,一边看电视,那么在水烧开的时候.由于太投入而没有注意到水被烧开. 丢失的信号 ...

  3. Java并发编程的艺术(十二)——线程安全

    1. 什么是『线程安全』? 如果一个对象构造完成后,调用者无需额外的操作,就可以在多线程环境下随意地使用,并且不发生错误,那么这个对象就是线程安全的. 2. 线程安全的几种程度 线程安全性的前提:对『 ...

  4. Java并发编程的艺术(十二)——并发容器和框架

    ConcurrentHashMap 为什么需要ConcurrentHashMap HashMap线程不安全,因为HashMap的Entry是以链表的形式存储的,如果多线程操作可能会形成环,那样就会死循 ...

  5. 转:【Java并发编程】之十二:线程间通信中notifyAll造成的早期通知问题(含代码)

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17229601 如果线程在等待时接到通知,但线程等待的条件还不满足,此时,线程接到的就是早期 ...

  6. 【Java并发编程】之十二:线程间通信中notifyAll造成的早期通知问题

    如果线程在等待时接到通知,但线程等待的条件还不满足,此时,线程接到的就是早期通知,如果条件满足的时间很短,但很快又改变了,而变得不再满足,这时也将发生早期通知.这种现象听起来很奇怪,下面通过一个示例程 ...

  7. java并发编程笔记(十)——HashMap与ConcurrentHashMap

    java并发编程笔记(十)--HashMap与ConcurrentHashMap HashMap参数 有两个参数影响他的性能 初始容量(默认为16) 加载因子(默认是0.75) HashMap寻址方式 ...

  8. 并发编程从零开始(十二)-Lock与Condition

    并发编程从零开始(十二)-Lock与Condition 8 Lock与Condition 8.1 互斥锁 8.1.1 锁的可重入性 "可重入锁"是指当一个线程调用 object.l ...

  9. 转: 【Java并发编程】之十八:第五篇中volatile意外问题的正确分析解答(含代码)

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17382679 在<Java并发编程学习笔记之五:volatile变量修饰符-意料之外 ...

随机推荐

  1. Windows进程间通讯(IPC)----内存映射文件

    内存映射文件原理 内存映射文件是通过在虚拟地址空间中预留一块区域,然后通过从磁盘中已存在的文件为其调度物理存储器,访问此虚拟内存空间就相当于访问此磁盘文件了. 内存映射文件实现过程 HANDLE hF ...

  2. Kafka万亿级消息实战

    一.Kafka应用 本文主要总结当Kafka集群流量达到 万亿级记录/天或者十万亿级记录/天  甚至更高后,我们需要具备哪些能力才能保障集群高可用.高可靠.高性能.高吞吐.安全的运行. 这里总结内容主 ...

  3. blazor发布之后 刷新404的解决方法

    其实所有单页面应用都一样 只需要在nginx里面配置 location / { root html; index index.html index.htm; rewrite ^/.*/$ / last ...

  4. C++ primer plus读书笔记——第10章 对象和类

    第10章 对象和类 1. 基本类型完成了三项工作: 决定数据对象需要的内存数量: 决定如何解释内存中的位: 决定可使用数据对象执行的操作或方法. 2. 不必在类声明中使用关键字private,因为这是 ...

  5. Django(21)migrate报错的解决方案

    前言 在讲解如何解决migrate报错原因前,我们先要了解migrate做了什么事情,migrate:将新生成的迁移脚本.映射到数据库中.创建新的表或者修改表的结构. 问题1:migrate怎么判断哪 ...

  6. 初窥软件工程 2020BUAA软件工程$\cdot$个人博客作业

    初窥软件工程 2020BUAA软件工程\(\cdot\)个人博客作业 目录 初窥软件工程 2020BUAA软件工程$\cdot$个人博客作业 一.作业要求简介 二.正文 (一) 快速看完整部教材,列出 ...

  7. Gateway导航

    简介 最近都在弄微服务的东西,现在来记录下收获.我从一知半解到现在能从0搭建使用最大的感触有两点 1.微服务各大组件的版本很多,网上很多博客内容不一定适合你的版本,很多时候苦苦琢磨都是无用功 2.网上 ...

  8. Advanced Archive Password Recovery (ARCHPR) 是一个强大的压缩包密码破解工具,适用于ZIP和RAR档案的高度优化的口令恢复工具。

    RAR压缩文件密码破解工具是一款简单易用的RAR文档和ZIP文档密码破解软件,如果你不小心忘了解压密码或是下载的RAR文件需要密码,那么均可以使用本软件进行暴力破解.不管WinRAR /RAR 的密码 ...

  9. 统一UOS操作系统 修改源地址

    统一UOS操作系统 修改源地址 问题: 执行apt-get update的时候提示: root@sugon-PC:/etc/apt# apt-get update -y错误:1 https://uos ...

  10. 【例 3】 修改 bols 文件的 atime 和 mtime。 [root@localhost ~]# touch -d "2017-05-04 15:44" bols

    Linux touch命令:创建文件及修改文件时间戳 < Linux删除空目录(rmdir命令)Linux在文件之间建立软/硬链接(ln命令) > <Linux就该这么学>是一 ...