共计 3936 个字符,预计需要花费 10 分钟才能阅读完成。
突击并发编程 JUC 系列演示代码地址:
https://github.com/mtcarpenter/JavaTutorial
上一个章节咱们学习原子更新根本类型类,如果没有印象的小伙伴能够通过底部的链接回头看下,本章节次要介绍原子更新数组类型。
数组类型
数组类型就是通过原子的形式更新数组里的某个元素,Atomic 包提供了以下 4 个类。
AtomicLongArray 罕用办法如下
办法名 | 阐明 |
---|---|
long getAndIncrement(int i) |
以原子形式将地位 i 处的元素原子设置为给定值,并返回旧值。 |
long incrementAndGet(int i) |
以原子形式将索引 i 处以原子形式自增元素,并返回减少之后的值。 |
long getAndDecrement(int i) |
以原子形式将索引 i 处的元素原子并自减1 ,并返回旧值。 |
long decrementAndGet(int i) |
以原子形式将索引 i 处的元素原子并自减1 ,并返回减少之后的值。 |
long addAndGet(int i, long delta) |
以原子形式将输出值与数组中索引 i 的元素相加。 |
long getAndSet(int i, long newValue) |
将地位 i 处的元素原子设置为给定值,并返回旧值。 |
long getAndIncrement(int i) |
原子地将给定的值增加到索引 i 的元素。 |
long get(int i) |
获取地位 i 的以后值。 |
void lazySet(int i, long newValue) |
最终将地位 i 处的元素设置为给定值。 |
int length() |
返回数组的长度。 |
void set(int i, long newValue) |
将地位 i 处的元素设置为给定值。 |
boolean compareAndSet(int i,int expect,int update) | 如果以后值 == 预期值,则以原子形式将数组地位 i 的元素设置成 update 值。 |
boolean weakCompareAndSet(int i, int expect, long update) |
如果以后值 == 期望值,则将地位 i 处的元素原子设置为给定的更新值。 |
…….. | …….. |
JDK 1.8 新增 |
|
long getAndUpdate(int i, LongUnaryOperator updateFunction) |
应用将给定函数利用给以后值和给定值的后果原子更新以后值,返回旧值 |
long updateAndGet(int i, LongUnaryOperator updateFunction) |
应用将给定函数利用给以后值和给定值的后果原子更新以后值,返回新值 |
…….. |
小试牛刀
指定大小
public class AtomicExample4 { | |
/** | |
* 初始化 数组长度为 10 | |
*/ | |
private static AtomicLongArray arr = new AtomicLongArray(5); | |
private static LongUnaryOperator longUnaryOperator = new LongUnaryOperator() { | |
@Override | |
public long applyAsLong(long operand) { | |
// 以后索引 + 10 | |
return operand + 10; | |
} | |
}; | |
private static LongBinaryOperator accumulatorFunction = new LongBinaryOperator() { | |
@Override | |
public long applyAsLong(long left, long right) {return left + right;} | |
}; | |
public static void main(String[] args) {for (int i = 0; i < arr.length(); i++) {System.out.println("i-" + i + "=" + arr.get(i)); | |
} | |
// 以原子形式给以后索引下标为(0)值加 1,返回新值(i++):0 | |
System.out.println("索引 0 incrementAndGet=" + arr.getAndIncrement(0)); | |
// 以原子形式给以后索引下标为(0)值加 1,,返回新值(++i)两次减少:2 | |
System.out.println("索引 0 incrementAndGet=" + arr.incrementAndGet(0)); | |
// 以原子形式给以后索引下标为(0)值缩小 1,返回旧值(i--):2 | |
System.out.println("索引 0 incrementAndGet=" + arr.getAndDecrement(0)); | |
// 以原子形式给以后索引下标为(0)值缩小 1,返回旧值(--i):0 | |
System.out.println("索引 0 incrementAndGet=" + arr.decrementAndGet(0)); | |
// 以原子形式将输出的数值与实例中的值(AtomicLongArray(0)里的 value)相加,并返回后果 : 100 | |
System.out.println("索引 0 addAndGet=" + arr.addAndGet(0, 100)); | |
// 获取 AtomicLongArray 的 value 100 | |
System.out.println("索引 0 get=" + arr.get(0)); | |
System.out.println("*********** JDK 1.8 ***********"); | |
// 应用将给定函数利用给以后值和给定值的后果原子更新以后值,返回上一个值 | |
// 索引下标为 0 执行指定函数 后果为 100 + 10 | |
System.out.println("索引 0 getAndUpdate=" + arr.updateAndGet(0, longUnaryOperator)); | |
// 索引下标为 1 执行指定函数 后果为 0 + 10 | |
System.out.println("索引 1 getAndUpdate=" + arr.updateAndGet(1, longUnaryOperator)); | |
// 应用给定函数利用给指定下标和给定值的后果原子更新以后值,并返回后果 20 | |
System.out.println("索引 1 accumulateAndGet=" + arr.accumulateAndGet(1, 10, accumulatorFunction)); | |
} | |
} |
运行后果如下:
i-0=0 | |
i-1=0 | |
i-2=0 | |
i-3=0 | |
i-4=0 | |
索引 0 incrementAndGet=0 | |
索引 0 incrementAndGet=2 | |
索引 0 incrementAndGet=2 | |
索引 0 incrementAndGet=0 | |
索引 0 addAndGet=100 | |
索引 0 get=100 | |
*********** JDK 1.8 *********** | |
索引 0 getAndUpdate=110 | |
索引 1 getAndUpdate=10 | |
索引 1 accumulateAndGet=20 |
通过数组
public class AtomicExample5 {public static void main(String[] args) { | |
/** | |
* 初始化 数组 | |
*/ | |
long arrs[] = {5, 20, 30, 40, 50}; | |
/** | |
* 将初始化数组的值 赋值给 AtomicLongArray | |
*/ | |
AtomicLongArray arr = new AtomicLongArray(arrs); | |
System.out.println("arr length=" + arr.length()); | |
for (int i = 0; i < arr.length(); i++) {System.out.println("i-" + i + "=" + arr.get(i)); | |
} | |
// 通过 set 给指定元素赋值 | |
arr.set(0, 10); | |
// 通过 get 获取下标为 0 的值 | |
System.out.println("索引 0 get =" + arr.get(0)); | |
// 如果 "指定索引的值" = "预期值" 就将指定的值更新为须要 "更新的值" | |
// 索引为 2 如果是 20 则相等,将值更新为 30 | |
arr.compareAndSet(2, 30, 300); | |
System.out.println("compareAndSet 更新索引 2 的值 =" + arr.get(2)); | |
// 与 compareAndSet 不论初始值是否为预期值都可能会无奈更新该值。arr.weakCompareAndSet(2, 300, 3000); | |
System.out.println("weakCompareAndSet 更新索引 2 的值 =" + arr.get(2)); | |
} | |
} |
-
留神常识
compareAndSet
: 指定索引值
和给定预期值
如果相等,则批改值为更新值
.weakCompareAndSet
: 此办法跟compareAndSet
相似,然而不论初始值是否为预期值都可能会无奈更新该值。
运行后果如下:
arr length=5 | |
i-0=5 | |
i-1=20 | |
i-2=30 | |
i-3=40 | |
i-4=50 | |
索引 0 get = 10 | |
compareAndSet 更新索引 2 的值 = 300 | |
weakCompareAndSet 更新索引 2 的值 = 3000 |
总结
通过原子的形式更新数组里的某个元素,Atomic 包提供了 4 个类, AtomicIntegerArray
、AtomicLongArray
、AtomicReferenceArray
、AtomicIntegerArray
,根本实现相似,在生活中应用频率比拟少,如果看过上一个章节的小伙伴应该对此章节的案例绝对就是驾轻就熟,还不是很相熟的小伙伴,倡议尝试在电脑中运行案例,或者本人编码实现。
欢送关注公众号 山间木匠, 我是小春哥,从事 Java 后端开发,会一点前端、通过继续输入系列技术文章与文会友,如果本文能为您提供帮忙,欢送大家关注、点赞、分享反对,咱们下期再见!
正文完