原子类的操作

原子类的操作

  1. AtomicInteger
    对于普通的变量操作,没有保证原子性。
public class IntegerPractice {
    static int a=0;
    public static void main(String[] args) {
        for(int j=0;j<6;j++)
        {
            new Thread(() -> {
                for (int i = 0; i <10 ; i++) {
                    a++;
                    try {
                        System.out.println(a);
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
}

执行结果如下
在这里插入图片描述
结果并不按照预期的那样,换成AtomicInteger:

/**
 * @author xiaobai
 */
public class IntegerPractice {

    public static void main(String[] args) {
        AtomicInteger ai=new AtomicInteger(0);
        ExecutorService es=new ThreadPoolExecutor(5,20,3, TimeUnit.SECONDS,new LinkedBlockingQueue<>());
        for(int i=0;i<6;i++)
        {
            es.submit(() -> {
                for (int j = 0; j < 10; j++) {
                    ai.incrementAndGet();
                    System.out.println(ai.get());
                }
            });
        }
    }
}

执行结果:
在这里插入图片描述
没有出现问题,保证了原子性。

2.更新数组,以AtomicIntegerArray为例:

/**
 - @author xiaobai
 */
public class IntegerArrayPractice {

    public static void main(String[] args) {
        int[] operation={1,2,3,4,5};//初始化数组
        AtomicIntegerArray aia=new AtomicIntegerArray(operation);
        System.out.println(aia.get(2));//获得数组索引为2的值
        System.out.println(aia.incrementAndGet(2));//数组索引为2的值加一
        System.out.println(aia.compareAndSet(2,6,4));//数组索引为2的值与6比较,相同就把该值更新为4,否则不更新值
        System.out.println(aia.get(2));
        System.out.println(aia.addAndGet(2,2));//数组索引为2的值加上2
        System.out.println(aia.compareAndSet(2,6,4));
        System.out.println(aia.get(2));
    }
}

运行结果:
在这里插入图片描述
3更新引用数据类型
以AtomicReference为例:

public class ReferencePractice {

    public static void main(String[] args) {
        String value="atomic reference";
        AtomicReference<String> ar=new AtomicReference<>(value);//初始化引用类型对象
        System.out.println(ar.get());//获得对象的值
        System.out.println(ar.compareAndSet("changed data","success"));//与期望字符串比较,相同就将值更新成"success",否则不更新
        ar.set("changed data");
        System.out.println(ar.get());
        System.out.println(ar.compareAndSet("changed data","success"));
        System.out.println(ar.get());
    }
}

运行结果:
在这里插入图片描述
4.原子更新字段
以AtomicIntegerFieldUpdater为例:

/**
 - @author xiaobai
 */
public  class IntegerFieldUpdaterPractice {

    int a;//a不是要操作的字段,所以可以不用关键词volatile修饰
    volatile int b;//b为操作的字段,前面要有volatile

    public IntegerFieldUpdaterPractice(int a,int b)
    {
        this.a=a;
        this.b=b;
    }

    public static void main(String[] args) {
        AtomicIntegerFieldUpdater<IntegerFieldUpdaterPractice> aifu=AtomicIntegerFieldUpdater.newUpdater(IntegerFieldUpdaterPractice.class,"b");//声明更新器,操作的类为IntegerFieldUpdaterPractice,操作这个类中的字段b
        IntegerFieldUpdaterPractice up=new IntegerFieldUpdaterPractice(2,3);//实例化对象
        System.out.println(aifu.get(up));//获得类中指定字段的值
        System.out.println( aifu.incrementAndGet(up));//对类中指定字段的值加一
        System.out.println(aifu.compareAndSet(up,8,6));//类中指定字段的值与5比较,相同就更新值为6,否则不更新
        System.out.println(aifu.get(up));
        System.out.println( aifu.addAndGet(up,4));//对类中指定字段的值加4
        System.out.println(aifu.compareAndSet(up,8,6));
        System.out.println(aifu.get(up));
    }
}

运行结果:
在这里插入图片描述
note:

  • 使用AtomicIntegerFieldUpdater初始得到更新器时需要指明需要操作的类以及类中字段值
  • 字段值需要volatile修饰,不修饰的话使用会报java.lang.IllegalArgumentException: Must be volatile type这种异常。
  • 变量应该为实例变量,不可以为类变量,即没有static关键词修饰。

5.jdk1.8新增的原子类
有DoubleAccumulator,DoubleAdder,LongAccumulator,LongAdder这四个类,
以LongAdder为例:

 public class LongAdderPractice {
    public static void main(String[] args) {
        LongAdder la=new LongAdder();//LongAdder初始值为0
        la.add(5);//对值进行加5
        System.out.println(la.sum());
        la.increment();
        System.out.println(la.sum());
    }
}

LongAdder内部有一个Cell类来计数,它的sum=base+各个Cell的和,LongAdder每个线程拥有自己的槽,各个线程一般只对自己槽中的那个值进行CAS操作,每个Cell对象都有一个value值,LongAdder通过Cell数组和base来求出最终的value值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值