Java AtomicInteger类使用方法实例讲解

 更新时间:2020年06月17日 10:45:14   作者:King-D  
这篇文章主要介绍了Java AtomicInteger类使用方法实例讲解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

1、java.util.concurrent.atomic 的包里有AtomicBoolean, AtomicInteger,AtomicLong,AtomicLongArray,
AtomicReference等原子类的类,主要用于在高并发环境下的高效程序处理,来帮助我们简化同步处理.

在Java语言中,++i和i++操作并不是线程安全的,在使用的时候,不可避免的会用到synchronized关键字。而AtomicInteger则通过一种线程安全的加减操作接口。

2、AtomicInteger的基本方法

创建一个AtomicInteger

System.out.println(atomicInteger.get());

--->输出 : 123

创建一个不传值的,默认值为0

AtomicInteger atomicInteger = new AtomicInteger();
System.out.println(atomicInteger.get());
---->输出: 0

获取和赋值

atomicInteger.get(); //获取当前值
atomicInteger.set(999); //设置当前值

atomicInteger.compareAndSet(expectedValue,newValue)

public static void main(String[] args) {
    AtomicInteger atomicInteger = new AtomicInteger(0);
    System.out.println(atomicInteger.get());

    int expectedValue = 123;
    int newValue   = 234;
    Boolean b =atomicInteger.compareAndSet(expectedValue, newValue);
    System.out.println(b);
    System.out.println(atomicInteger);

  }

----》输出结果为: 0 false 0


 public static void main(String[] args) {
    AtomicInteger atomicInteger = new AtomicInteger(123);
    System.out.println(atomicInteger.get());

    int expectedValue = 123;
    int newValue   = 234;
    Boolean b =atomicInteger.compareAndSet(expectedValue, newValue);
    System.out.println(b);
    System.out.println(atomicInteger);

  }
-----》输出结果为: 123 true 234

由上可知该方法表示,atomicInteger的值与expectedValue相比较,如果不相等,则返回false,
atomicInteger原有值保持不变;如果两者相等,则返回true,atomicInteger的值更新为newValue

getAndAdd()方法与AddAndGet方法

AtomicInteger atomicInteger = new AtomicInteger(123);
    System.out.println(atomicInteger.get()); --123

    System.out.println(atomicInteger.getAndAdd(10)); --123 获取当前值,并加10
    System.out.println(atomicInteger.get()); --133


    System.out.println(atomicInteger.addAndGet(10)); --143 获取加10后的值,先加10
    System.out.println(atomicInteger.get()); --143

getAndDecrement()和DecrementAndGet()方法

AtomicInteger atomicInteger = new AtomicInteger(123);
    System.out.println(atomicInteger.get());  --123
    System.out.println(atomicInteger.getAndDecrement()); --123 获取当前值并自减
    System.out.println(atomicInteger.get()); --122
    System.out.println(atomicInteger.decrementAndGet()); --121 先自减再获取减1后的值
    System.out.println(atomicInteger.get()); --121

3、使用AtomicInteger,即使不用同步块synchronized,最后的结果也是100,可用看出AtomicInteger的作用,用原子方式更新的int值。主要用于在高并发环境下的高效程序处理。使用非阻塞算法来实现并发控制。

public class Counter {

  public static AtomicInteger count = new AtomicInteger(0);

  public static void inc(){
    try{
      Thread.sleep(1); //延迟1毫秒

    }catch (InterruptedException e){ //catch住中断异常,防止程序中断
      e.printStackTrace();

    }
    count.getAndIncrement();//count值自加1
  }


  public static void main(String[] args) throws InterruptedException {


    final CountDownLatch latch = new CountDownLatch(100);

    for(int i=0;i<100;i++){
      new Thread(new Runnable() {
        @Override
        public void run() {
          Counter.inc();
          latch.countDown();
        }
      }).start();
    }
    latch.await();

    System.out.println("运行结果:"+Counter.count);
  }
}

运行结果: 100

4、使用普通Integer

public class Counter {

  public volatile static int count = 0;

  public static void inc(){
    try{
      Thread.sleep(1); //延迟1毫秒

    }catch (InterruptedException e){ //catch住中断异常,防止程序中断
      e.printStackTrace();

    }
    count++;//count值自加1
  }


  public static void main(String[] args) throws InterruptedException {


    final CountDownLatch latch = new CountDownLatch(100);

    for(int i=0;i<100;i++){
      new Thread(new Runnable() {
        @Override
        public void run() {
          Counter.inc();
          latch.countDown();
        }
      }).start();
    }
    latch.await();

    System.out.println("运行结果:"+Counter.count);
  }
}
运行结果:98

5、如果在inc方法前面加个synchronized也能是线程安全的;

它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。

import java.util.concurrent.CountDownLatch;
/**
 * created by guanguan on 2017/10/23
 **/
public class Counter {
   public volatile static Integer count = 0;
  public synchronized static void inc(){
    try{
      Thread.sleep(1); //延迟1毫秒
    }catch (InterruptedException e){ //catch住中断异常,防止程序中断
      e.printStackTrace();
    }
     count++;//count值自加1
  }
  public static void main(String[] args) throws InterruptedException {
    final CountDownLatch latch = new CountDownLatch(100);
    for(int i=0;i<100;i++){
      new Thread(new Runnable() {
        @Override
        public void run() {
          Counter.inc();
          latch.countDown();
        }
      }).start();
    }
    latch.await();
    System.out.println("运行结果:"+Counter.count);
  }
}
运行结果:100

synchronized的使用说明:

一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

五、以上规则对其它对象锁同样适用.

6、从上面的例子中我们可以看出:使用AtomicInteger是非常的安全的.而且因为AtomicInteger由硬件提供原子操作指令实现的。在非激烈竞争的情况下,开销更小,速度更快。

java的关键域有3个

// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
private volatile int value;

这里, unsafe是java提供的获得对对象内存地址访问的类,注释已经清楚的写出了,它的作用就是在更新操作时提供“比较并替换”的作用。实际上就是AtomicInteger中的一个工具。

valueOffset是用来记录value本身在内存的便宜地址的,这个记录,也主要是为了在更新操作在内存中找到value的位置,方便比较。

注意:value是用来存储整数的时间变量,这里被声明为volatile,就是为了保证在更新操作时,当前线程可以拿到value最新的值(并发环境下,value可能已经被其他线程更新了)。

这里,我们以自增的代码为例,可以看到这个并发控制的核心算法:

源码

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • java学习之JVM运行时常量池理解

    java学习之JVM运行时常量池理解

    这篇文章主要介绍了java学习之JVM运行时常量池理解,对常量池的好处以及基本类型的包装类常量池等作了简要分析,有需要的朋友可以借鉴参考下
    2021-09-09
  • Java Agent 动态修改字节码详情

    Java Agent 动态修改字节码详情

    这篇文章主要介绍了Java Agent动态修改字节码的相关资料,需要的朋友可以参考下面文章具体的内容
    2021-09-09
  • spring boot实战之内嵌容器tomcat配置

    spring boot实战之内嵌容器tomcat配置

    本篇文章主要介绍了Spring Boot 使用内嵌的tomcat容器配置,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • IntelliJ IDEA 使用经验总结(推荐)

    IntelliJ IDEA 使用经验总结(推荐)

    这篇文章主要介绍了IntelliJ IDEA 使用经验总结,非常不错,具有参考价值,需要的朋友可以参考下
    2018-02-02
  • Java如何获取主机的基本信息详解

    Java如何获取主机的基本信息详解

    最近遇到一个工作需求,上网查了一下怎样在Java中获取本机的ip和主机名,所以下面这篇文章主要给大家介绍了关于Java如何获取主机的基本信息,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2021-12-12
  • Java 程序设计总复习题(java基础代码)

    Java 程序设计总复习题(java基础代码)

    这篇文章主要介绍了Java 程序设计总复习题,主要是java基础代码,方便学习java的同学
    2021-05-05
  • JAVA开发环境Vs code配置步骤详解

    JAVA开发环境Vs code配置步骤详解

    这篇文章主要为大家介绍了JAVA开发环境Vs code配置步骤详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-04-04
  • Spring中SmartLifecycle和Lifecycle的作用和区别

    Spring中SmartLifecycle和Lifecycle的作用和区别

    这篇文章主要介绍了Spring中SmartLifecycle和Lifecycle的作用和区别,本文通过实例代码给大家介绍的非常详细对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • PowerJob的AliOssService工作流程源码解读

    PowerJob的AliOssService工作流程源码解读

    这篇文章主要介绍了PowerJob的AliOssServiceg工作流程源码解读,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01
  • springboot+idea热启动设置方法(自动加载)

    springboot+idea热启动设置方法(自动加载)

    这篇文章主要介绍了springboot+idea热启动设置方法(自动加载),本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-01-01

最新评论