Java原子类中的AtomicInteger类详解

 更新时间:2023年10月24日 09:34:08   作者:liyong0829  
这篇文章主要介绍了Java原子类中的AtomicInteger类详解,原子类可以保证对"变量"操作的,原子性、有序性、可见性,我们可以通过AtomicInteger类,来看看它们是怎样工作的,需要的朋友可以参考下

原子类

在java.util.concurrent.atomic包下定义了一些对“变量”操作的“原子类”:

  • java.util.concurrent.atomic.AtomicInteger:对int变量操作的“原子类”;
  • java.util.concurrent.atomic.AtomicLong:对long变量操作的“原子类”;
  • java.util.concurrent.atomic.AtomicBoolean:对boolean变量操作的“原子类”;

它们可以保证对“变量”操作的:原子性、有序性、可见性。

AtomicInteger类示例

我们可以通过AtomicInteger类,来看看它们是怎样工作的

//线程类:

public class MyThread extends Thread {
     //static int a = 0;
    static AtomicInteger a = new AtomicInteger();// 表示整数0

    @Override
    public void run() {
        for (int i = 0; i < 200000; i++) {
            // a++;
            a.getAndIncrement();
        }
        System.out.println("子线程执行完毕");
    }
}

//测试类:

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

        // 案例:一条子线程和一条主线程都对共享变量a进行++操作,每条线程对a++操作400000次
        new MyThread().start();

        for (int i = 0; i < 200000; i++) {
            //MyThread.a++;
            MyThread.a.getAndIncrement();
        }

        // 为了保证子线程和主线程都执行完毕
        Thread.sleep(3000);

        // 打印最终共享变量a的值(子线程,主线程对a的操作都执行完毕了)
        System.out.println("最终:"+ MyThread.a.get());

  }
}

我们能看到,无论程序运行多少次,其结果总是正确的!

AtomicInteger类的工作原理-CAS机制

在这里插入图片描述

AtomicIntegerArray类示例

常用的数组操作的原子类:

1).java.util.concurrent.atomic.AtomicIntegerArray:对int数组操作的原子类。 int[]

2).java.util.concurrent.atomic.AtomicLongArray:对long数组操作的原子类。long[]

3).java.util.concurrent.atomic.AtomicReferenceArray:对引用类型数组操作的原子类。Object[]

数组的多线程并发访问的安全性问题:

//线程类:

public class MyThread extends Thread {
    public static int[] arr = new int[1000];

    @Override
    public void run() {
        for (int i = 0; i < arr.length(); i++) {
            arr[i]++;
        }
        System.out.println("结束");
    }
}

//测试类:

public class Demo {
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 1000; i++) {
            new MyThread().start();//创建1000个线程,每个线程为数组的每个元素+1
        }

        Thread.sleep(1000 * 5);//让所有线程执行完毕

        System.out.println("主线程休息5秒醒来");
        for (int i = 0; i < MyThread.arr.length; i++) {
            System.out.println(MyThread.arr[i]);
        }
    }
}

//正常情况,数组的每个元素最终结果应为:1000,而实际打印:

1000
1000
1000
1000
999
999
999
999
999
999
999
999
1000
1000
1000
1000

可以发现,有些元素并不是1000.

//为保证数组的多线程安全,改用AtomicIntegerArray类,演示:

//线程类:

public class MyThread extends Thread {
 
    //改用原子类,使用数组构造
    public static AtomicIntegerArray arr = new AtomicIntegerArray(1000);
    @Override
    public void run() {
        for (int i = 0; i < arr.length(); i++) {
            arr.addAndGet(i, 1);//将i位置上的元素 + 1
        }
        System.out.println("结束");
    }
}

测试类 

  public class Demo {
      public static void main(String[] args) throws InterruptedException {
          for (int i = 0; i < 1000; i++) {
              new MyThread().start();
          }
          Thread.sleep(1000 * 5);//让所有线程执行完毕
  
          System.out.println("主线程休息5秒醒来");
          for (int i = 0; i < MyThread.arr.length(); i++) {
              System.out.println(MyThread.arr.get(i));
          }
      }
  }

先在能看到,每次运行的结果都是正确的。

到此这篇关于Java原子类中的AtomicInteger类详解的文章就介绍到这了,更多相关Java的AtomicInteger类内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java类加载初始化的过程及顺序

    Java类加载初始化的过程及顺序

    今天小编就为大家分享一篇关于Java类加载初始化的过程及顺序,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • 简单谈谈Spring Ioc原理解析

    简单谈谈Spring Ioc原理解析

    学习过Spring框架的人一定都会听过Spring的IoC(控制反转) 、DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC 、DI这两个概念是模糊不清的,是很难理解的,今天和大家分享网上的一些技术大牛们对Spring框架的IOC的理解以及谈谈我对Spring Ioc的理解。
    2018-09-09
  • com.mysql.jdbc.Driver 和 com.mysql.cj.jdbc.Driver的区别及设定serverTimezone的方法

    com.mysql.jdbc.Driver 和 com.mysql.cj.jdbc.Driver的区

    这篇文章主要介绍了com.mysql.jdbc.Driver 和 com.mysql.cj.jdbc.Driver的区别以及设定serverTimezone的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-09-09
  • java开发时各类工具的使用规范

    java开发时各类工具的使用规范

    这篇文章主要介绍了java编码时各类工具的使用规范,多人协作、共同开发一个项目,如果没有统一的代码规范的话,项目中的每个人都按照自己的习惯率性而为,就会导致整个项目的代码看上去杂乱无章,可读性非常差,并且持续增加后续的维护成本。对此感兴趣可以来了解一下
    2020-07-07
  • Java中的递归方法示例介绍

    Java中的递归方法示例介绍

    大家好,本篇文章主要讲的是Java中的递归方法示例介绍,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2021-12-12
  • Java利用Reflect实现封装Excel导出工具类

    Java利用Reflect实现封装Excel导出工具类

    这篇文章主要为大家详细介绍了Java如何利用Reflect实现封装Excel导出工具类,文中的实现方法讲解详细,具有一定的借鉴价值,需要的可以参考一下
    2022-11-11
  • Java实现的简单数字时钟功能示例

    Java实现的简单数字时钟功能示例

    这篇文章主要介绍了Java实现的简单数字时钟功能,涉及java日期时间及JFrame框架图形界面操作相关实现技巧,需要的朋友可以参考下
    2019-02-02
  • Spring boot 整合RabbitMQ实现通过RabbitMQ进行项目的连接

    Spring boot 整合RabbitMQ实现通过RabbitMQ进行项目的连接

    RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端,这篇文章主要介绍了Spring boot 整合RabbitMQ实现通过RabbitMQ进行项目的连接,需要的朋友可以参考下
    2022-10-10
  • 为什么Java要把字符串设计成不可变的

    为什么Java要把字符串设计成不可变的

    为什么Java要把字符串设计成不可变的,这篇文章给出了Java字符串设计成不可变的原因,感兴趣的小伙伴们可以参考一下
    2017-06-06
  • Java读取String分行字符串的方法

    Java读取String分行字符串的方法

    今天小编就为大家分享一篇Java读取String分行字符串的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-07-07

最新评论