AtomicInteger-java原子操作包-java多线程100例-9

我们知道在java多线程中使用sychronized和reentrantlock可以保证只有一个线程进入代码块,从而可以保证可见性,顺序性和原则性。但是这样做的效率比较低, 明明是多线程的工作,执行到这一块儿的时候就变成单线程了。

使用volatile修饰变量可以保证其可见性和顺序性,但是却不能保证其原则性,想要实现原则性可以了解下接下来介绍的java多谢的的automic包锁提供的下面工具:

java.util.concurrent.atomic, 在atomic工具包下面有下面这么多个类, 其实用嘴简单的话来介绍其就值解决了一个问题就是,对值进行改变,例如对int值,long值,数组,引用类型,引用类型中的成员变量进行赋值,因为赋值操作不熟原则的,所以想要原子的改变每个值又不使用锁的情况下就可以用这个包的工具帮你解决问题:

x = a 

如下截图:

我们可以分成四个类型:

第一个类型:

对基本数据类型进行值得改变:

如图红色部分:

AtomicBoolean
AtomicInteger
AtomicLong

常用到的方法有:

int get() 获取当前值。
void set(int newValue) 设置为给定值。
int addAndGet(int delta) 将给定值与当前值相加返回结果。
int decrementAndGet() 当前值减 1并返回结果。
int incrementAndGet() 当前值加 1变返回结果。

   @Test
    public void testAtomicInterger(){
        AtomicInteger integer = new AtomicInteger(0);
        System.out.println(integer.get()); //i
        integer.set(10); //i=10
        System.out.println(integer.get());//i
        System.out.println(integer.addAndGet(10));//i=i+10
        System.out.println(integer.incrementAndGet());//++i
        System.out.println(integer.decrementAndGet());//--i
    }

执行结果:

第二个类型:

对数组进行原则操作

AtomicIntegerArray   原子更新int型数组
AtomicLongArray      原子更新long型数组
AtomicReferenceArray 原子更新引用数组

常用方法:

int get(int i)                            // i
void set(int i, int newValue)   // a[i]=newValue
int length()                             // a.length()
int getAndAdd(int i, int delta) // a[i]=a[i]+delta
int getAndDecrement(int i)    // i++
int getAndIncrement(int i)      // i--
AtomicIntegerArray(int length)  // new [length] Array()

例子一操作普通数组:

@Test
    public void testAtomicArray(){
       int [] array = new int[]{1,2,3,4,5};

        AtomicIntegerArray atomicArray = new AtomicIntegerArray(array);

        System.out.println(atomicArray.get(3));
        System.out.println(atomicArray.addAndGet(0,10));
        System.out.println(atomicArray.incrementAndGet(0));
        System.out.println(atomicArray.decrementAndGet(0));
    
        for (int i = 0; i < atomicArray.length(); i++) {
            System.out.println(atomicArray.get(i));
        }
}

执行结果:

实例 二,操作二维数组:

    @Test
    public void testAtomic2Array(){
        int [] array0 = new int[]{1,2,3,4,5};
        int [] array1 = new int[]{6,7,8,9,10};

        AtomicIntegerArray atomicArray1 = new AtomicIntegerArray(array0);
        AtomicIntegerArray atomicArray2 = new AtomicIntegerArray(array1);

        AtomicIntegerArray [] refA = new AtomicIntegerArray []{atomicArray1,atomicArray2};

        AtomicReferenceArray <AtomicIntegerArray> refArray = new AtomicReferenceArray(refA);

        System.out.println( refArray.get(0).get(0));
        System.out.println( refArray.get(1).get(0));

    }

执行结果:

第三个类型:

对类中的成员变量进行值更改, 注意类里面的变量不能是private的,而且必须由valotile修饰。

AtomicIntegerFieldUpdater   原子更新整型的字段的更新器
AtomicLongFieldUpdater      原子更新长整型的字段更新器

AtomicReferenceFieldUpdater 原子更新引用类型的字段更新器

    @Test
    public void testAtomicField(){
        Child child = new Child();

        AtomicIntegerFieldUpdater intField =  AtomicIntegerFieldUpdater.newUpdater(Child.class,"age");
        AtomicReferenceFieldUpdater  strField =  AtomicReferenceFieldUpdater.newUpdater(Child.class,String.class,"name");

        intField.set(child,20);
        strField.set(child,"Allen");

        System.out.println("age : " + child.age);
        System.out.println("name : " + child.name);

    }

public class Child {
    public volatile String name;
    public volatile int age;
}

第四个类型

AtomicReference                 引用类型的变量赋值改变
AtomicStampedReference   引用类型的变量赋值改变并带版本号,解决ABA问题

AtomicReference  实现的功能就是和Child c = c1; 这样的功能,目的是实现原则性的引用类型赋值。

AtomicStampedReference   加了版本功能,每次赋值必须传入争取的版本号, 如果版本号不对就不会赋值成功如下例子。

    @Test
    public void testAtomicRef(){
        Child child = new Child("Allen",18);
        Child child1 = new Child("LiSang",19);
        Child child2 = new Child("Wang",20);

        AtomicReference <Child> childRef= new AtomicReference<Child> (child);
        childRef.set(child1);

        System.out.println(childRef.get().name);


        AtomicInteger atomicInt = new AtomicInteger(0);
        AtomicStampedReference <Child> childSRef= new AtomicStampedReference<Child> (child,atomicInt.getAndIncrement());
        childSRef.set(child1,atomicInt.getAndIncrement());

        System.out.println(childRef.get().name+ " " +atomicInt.get());

        childSRef.set(child2,atomicInt.getAndIncrement());

        System.out.println(childRef.get().name+ " " +atomicInt.get());

        childSRef.set(child,0);

        System.out.println(childRef.get().name+ " " +atomicInt.get());
    }

public class Child {
    public volatile String name;
    public volatile int age;

    public Child (){
    }

   public Child (String name, int age){
        this.name = name;
        this.age =  age;
    }
}

执行结果:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值