原子类

什么是原子类

  以前认为原子是不可分割的最小单位。故原子类可以认为其操作时不可分割的。

  为什么要有原子类

    对多线程访问同一变量,我们需要加锁,而锁是比较消耗性能的,jdk1.5之后,新增的原子操作类提供了一种简单、性能高效、线程安全地更新一个变量的方式,这些类同样位于juc包下的atomic包下,发展到jdk1.8,该报共有17个类,囊括了原子更新基本类型、原子更新数组、原子更新新属性、原子更新引用。

  1.8新增的原子类

    DoubleAccumulator、DoubleAdder、LongAccumulator、LongAdder、LongAccumulator、LongAdder

   大致可归为三类

       AtomicBoolean、AtomicIndteger、AutomicLong  元老级的原子更新,方法几乎一模一样

       DoubleAdder、LongAdder 对Double、Long的原子更新性能进行优化提升

       DoubleAccumulator、LongAccumlator 支持自定义运算

  原子更新数组类型

       AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray

  原子的更新属性

       原子的更新某个类里的字段时,需要使用原子更新字段类,AtomicStampedReference、AtomicReference、FiledUpdater

      使用上述类是必须遵循以下原则

        字段必须是voliatile类型的,在线程之间共享变量时能保持可见性。

        字段的描述类型是与调用者的操作对象字段保持一致。

        也就是说调用者可以直接操作对象字段,那么就可以反射进行原子操作。

        对父类的字段,子类不能直接操作的,尽管子类可以访问父类的字段

        只能是实例变量,不能是类变量,也就是说不能加static关键字

        只能是可修改变量,不能使用final修饰变量,final的语义,不可更改。

        对于AtomicIntegerFieldUpdater和AtomicLongFieldUpdater只能修改int/long类型的字段,不能修改其包装类型                           (Integer/Long)

        如果需要修改包装类型就需要使用AtomicReferenceFieldUpdater。

下面写几个原子类使用的简单例子

1.AtomicIndteger实现一个线程安全的自增

import java.util.concurrent.atomic.AtomicInteger;

/**
 * AtomicInteger  demo
 */
public class AtomicIntegerDemo {
    private static AtomicInteger sum = new AtomicInteger(0);

    public static void  increase(){
        sum.incrementAndGet();
    }

    public static void main(String[] args) throws InterruptedException{
        for (int i=0;i<10;i++){
            new Thread(()->{
                for (int j=0;j<10;j++){
                    increase();
                    System.out.println(sum);
                }
            }).start();

        }

    }
}

2.LongAccumulator Long类型的原子运算

import java.util.concurrent.atomic.LongAccumulator;

public class LongAccumulatorDemo {
    public static void main(String[] args) {
        LongAccumulator longAccumulator = new LongAccumulator((left,right)->
        left<right?right:left,0l);
        longAccumulator.accumulate(3);

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

        longAccumulator.accumulate(6);

        System.out.println(longAccumulator.get());
    }
}

   运行结果

   

3.AtomicIntegerArray 原子更新int数组元素

import java.util.concurrent.atomic.AtomicIntegerArray;

public class AtomicIntegerArrayDemo {

    public static void main(String[] args) {
        int[] arr = new int[]{3,2};

        AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(arr);


        System.out.println("arr数组下标为1的元素的值加3等于:"
                +atomicIntegerArray.addAndGet(1, 3));

        System.out.println("arr数组下标为0的元素的值同2比较,较大的值为:"
                +atomicIntegerArray.accumulateAndGet(0, 2, ((left, right) -> left>right?left:right)));
    }
}

   

4.原子更新属性,先创建一个简单的Student类,方便后面的测试

public class Student {
    volatile long id;
    volatile String name;

    public Student(Long id, String name) {
        this.id = id;
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

  4.1AtomicLongFieldUpdater 更新long类型属性 ,AtomicReferenceFieldUpdater 更新String类型属性

import java.util.concurrent.atomic.AtomicLongFieldUpdater;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

public class AtomicFieldUpdaterDemo {

    public static void main(String[] args) {
        //更新long类型属性
        AtomicLongFieldUpdater<Student> atomicLongFieldUpdater = AtomicLongFieldUpdater.newUpdater(Student.class, "id");

        Student student = new Student(1L,"lisi");
        atomicLongFieldUpdater.compareAndSet(student, 1L, 101l);
        System.out.println("更新long类型的属性id:"+student.getId());

        //更新包装类型属性
        AtomicReferenceFieldUpdater<Student,String> atomicReferenceFieldUpdater = AtomicReferenceFieldUpdater.newUpdater(Student.class, String.class,"name" );

        atomicReferenceFieldUpdater.compareAndSet(student, "lisi", "zhangsan");

        System.out.println("更新String类型的属性name:"+student.getName());
    }

}

运行结果:

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值