jdk8 java.util包整体学习(二)concurrent.atomic包下的类

前言

java.util.concurrent.atomic 包下共有 17个类。统计代码如下

    public static void main(String[] args) throws IOException {
        JarFile jarFile = new JarFile("/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/rt.jar");
        Enumeration<JarEntry> jarEntries = jarFile.entries();
        AtomicInteger num = new AtomicInteger();
        String packageStr = "java/util/concurrent/atomic";
        jarFile.stream().forEach(m->{
            if(m.getName().startsWith(packageStr) && !m.getName().contains("$") && m.getName().endsWith("class")){
                System.out.println(m.getName().substring(m.getName().indexOf(packageStr)+packageStr.length()+1));
                num.getAndIncrement();
            }
        });
        System.out.println("共有类:"+num.toString());
    

结果如下:
在这里插入图片描述

包简介

atmic 包主要支持单变量上的无锁线程安全编程。
分类:

  • 原子更新基本类型类
    • AtomicBoolean:原子更新布尔类型。
    • AtomicInteger:原子更新整型。
    • AtomicLong:原子更新长整型。
  • 原子更新数组类
    • AtomicIntegerArray:原子更新整型数组里的元素。
    • AtomicLongArray:原子更新长整型数组里的元素。
    • AtomicReferenceArray:原子更新引用类型数组里的元素。
  • 原子更新引用类型
    • AtomicReference:原子更新引用类型。
    • AtomicReferenceFieldUpdater:原子更新引用类型里的字段。
    • AtomicIntegerFieldUpdater:原子更新整型的字段的更新器。
    • AtomicLongFieldUpdater:原子更新长整型字段的更新器。
    • AtomicStampedReference:原子更新带有版本号的引用类型。该类将整数值与引用关联起来,可用于原子的更数据和数据的版本号,可以解决使用CAS进行原子更新时,可能出现的ABA问题。
  • 针对 Atomic 相关数字类的改进类
    • LongAdder
    • LongAccumulator
    • DoubleAdder
    • DoubleAccumulator

原子更新基本类型

AtomicBoolean

常用方法:

  • public final boolean compareAndSet(boolean expect,
    boolean update)
    如果当前值 == 预期值,则以原子方式将该值设置为给定的更新值。
    参数:
    expect - 预期值
    update - 新值
    返回:
    如果成功,则返回 true。返回 False 指示实际值与预期值不相等。
  • getAndSet
    public final boolean getAndSet(boolean newValue)
    以原子方式设置为给定值,并返回以前的值。
    参数:
    newValue - 新值
    返回:
    以前的值

AtomicInteger

常用方法(如果涉及加减,则只列举加):

  • incrementAndGet 自增,返回最新的值
  • addAndGet 做加法,并返回最新的值
  • compareAndSet 设置值,并返回是否设置成功

AtomicLong

常用方法(如果涉及加减,则只列举加):

  • incrementAndGet 自增,返回最新的值
  • addAndGet 做加法,并返回最新的值
  • compareAndSet 设置值,并返回是否设置成功

原子更新数组类

注意:

  • 原子更新数组类不会直接操作传入的数组,而是操作自己 clone 的传入的数组的副本

AtomicIntegerArray

常用方法:

  • addAndGet(int i, int delta) cas 更新下标为 i 的数字为 当前数+delta,并返回最新值
  • incrementAndGet(int i) cas 下标为 i 的元素进行自增,并返回最新值
  • compareAndSet(int i, int expect, int update) 比较下标为 i 的元素和 expect,相等则更新为 update,返回是否更新成功

AtomicLongArray

类似 AtomicIntegerArray

AtomicReferenceArray

常用方法:

  • compareAndSet(int i, E expect, E update) 比较下标为 i 的引用和 expect 是否相同,相同的话,则将引用更新为 update。返回值为是否更新

原子更新引用类型

AtomicReference

原子更新引用

AtomicReferenceFieldUpdater

原子更新引用对象字段。这个类是基于反射的一个工具类。被更新的字段需要满足以下要求:

  • 被 volatile 修饰(保证可见行)
  • 不能被 private 修饰符修饰

核心方法:

  • AtomicReferenceFieldUpdater<U,W> newUpdater(Class< U> tclass,
    Class< W> vclass,
    String fieldName) 生成一个更新器。
  • compareAndSet(T obj, V expect, V update) 比较并跟新 obj 的字段值,并返回是否成功更新

使用示例:

    @org.junit.Test
    public void testAtomicReferenceFieldUpdater(){
        Person person = new Person("小田切让",20);
        AtomicReferenceFieldUpdater fieldUpdater = AtomicReferenceFieldUpdater.newUpdater(Person.class,Integer.class,"age");
        fieldUpdater.compareAndSet(person,person.getAge(),new Integer(33));
        System.out.println(person.getAge());
    }
@AllArgsConstructor
@Data
class Person{
    private String name;

    public volatile Integer age;
}

AtomicIntegerFieldUpdater

修改引用对象中被 int 修饰的字段。该字段必须满足以下要求:

  • 被 int 修饰,不能使用包装类型 Integer 修饰
  • 必须被 volatile 修饰
  • 不能被 private 修饰

常用方法:

  • newUpdater(Class tclass,String fieldName) 生成字段更新器
  • incrementAndGet(T obj) obj 的字段自增,并返回最新值
  • compareAndSet(T obj, int expect, int update)

示例:

    @org.junit.Test
    public void testAtomicIntegerFieldUpdater(){
        Person person = new Person("小田切让",new Integer(20));
        AtomicIntegerFieldUpdater<Person> updater  = AtomicIntegerFieldUpdater.newUpdater(Person.class,"age");
        updater.incrementAndGet(person);
        updater.compareAndSet(person,person.getAge(),new Integer(25));
        System.out.println(person.getAge());
    }

@AllArgsConstructor
@Data
class Person{
    private String name;

    public volatile int age;
}

AtomicLongFieldUpdater

类似 AtomicIntegerFieldUpdater ,修改引用对象中被 long 修饰的字段。该字段必须满足以下要求:

  • 被 long 修饰,不能使用包装类型 Long 修饰
  • 必须被 volatile 修饰
  • 不能被 private 修饰

AtomicStampedReference

解决原子更新引用的「ABA」问题

常用方法:

  • compareAndSet(V expectedReference,
    V newReference,
    int expectedStamp,
    int newStamp) 比较引用和标志,都相同才进行更新,并返回更新结果

示例:

    @org.junit.Test
    public void testAtomicStampedReference(){
        Person person = new Person("小田切让",20);
        AtomicStampedReference<Person> reference = new AtomicStampedReference<>(person,100);
        reference.compareAndSet(person,new Person("小栗旬",23),100,101);
        System.out.println(reference.getReference().getName());
        System.out.println(reference.getStamp());
    }

针对 Atomic 相关数字类的改进类

LongAdder

针对 AtomicLong 的改进类,在高并发的情况下,拥有更好的表现
常用方法:

  • add(long x) 加法
  • increment() 自增
  • decrement() 自减

DoubleAdder

常用方法:

  • add(double x)

LongAccumulator

LongAdder 只提供了「加」操作,假如需要对当前结果 m 进行 m*5+1,这种复合运算,则需要 LongAccumulator。
ongAdder类是LongAccumulator的一个特例,LongAccumulator提供了比LongAdder更强大的功能,如下构造函数,其中accumulatorFunction是一个双目运算器接口,根据输入的两个参数返回一个计算值(两个参数分别代表,当前值,输入值),identity则是LongAccumulator累加器的初始值。
常用方法:

  • LongAccumulator(LongBinaryOperator accumulatorFunction,
    long identity)
  • accumulate(long x) 进行一次计算

demo:

    @org.junit.Test
    public void testLongAccumulator(){
        LongAccumulator longAccumulator = new LongAccumulator((m,n)-> {
            return m*n+1; // 这里结果其实是 100 * 10 +1
        },100);
        longAccumulator.accumulate(10);
        System.out.println(longAccumulator.longValue());
    }

DoubleAccumulator

类似 LongAccumulator

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值