博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java AtomicInteger的用法
阅读量:6715 次
发布时间:2019-06-25

本文共 6234 字,大约阅读时间需要 20 分钟。

hot3.png

1.java.util.concurrent.atomic 的包里有AtomicBoolean, AtomicInteger,AtomicLong,AtomicLongArray,

AtomicReference等原子类的类,主要用于在高并发环境下的高效程序处理,来帮助我们简化同步处理.

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

2.AtomicInteger的基本方法

  • 创建一个AtomicInteger
AtomicInteger atomicInteger = new AtomicInteger(123);  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;    }

 

转载于:https://my.oschina.net/u/2263272/blog/1555071

你可能感兴趣的文章
idea之debug
查看>>
什么是真正的流程管理?流程管理的是与不是。
查看>>
SEO实践:SEO友好的URL结构
查看>>
洛谷P1613 跑路
查看>>
python各种模块,迭代器,生成器
查看>>
微信小程序 watch监听数据变化 类似vue中的watch
查看>>
u检验、t检验、F检验、X2检验 (转)
查看>>
不可不知的Python模块: collections
查看>>
PAT 1066. Root of AVL Tree (25)
查看>>
hdu1052
查看>>
服务器端推送技术
查看>>
python开发工具
查看>>
Home Assistant系列 -- 自动语音播报天气
查看>>
Hyberledger-Fabric 1.00 RPC学习(1)
查看>>
SDNU 1450.报时助手
查看>>
BZOJ 4144 Dijkstra+Kruskal+倍增LCA
查看>>
阻塞与非阻塞,同步与异步
查看>>
HTML段落自动换行的样式设置
查看>>
Android实现左右滑动指引效果
查看>>
html里frame导航框架实现方法
查看>>