Java8中有哪些原子类呢?
下文笔者讲述原生态的jdk8的原子类(线程安全类)
AtomicBoolean AtomicInteger AtomiclIntegerArray AtomiclntegerFieldUpdater AtomicLong AtomicLongArray AtomicLongFieldUpdater AtomicMarkableReference AtomicReference AtomicReferenceArray AtomicReferenceFieldUpdater AtomicStampedReference JDK8时新增了4个原子操作类 如下: DoubleAccumulator DoubleAdder LongAccumulatorLongAdder
Atomic包操作基本数据类型,可使用以下原子类
AtomicBoolean:原子更新布尔类型 AtomicInteger:原子更新整型 AtomicLong:原子更新长整型这些基础类提供一些常见的方法
int addAndGet(int delta):
以原子的方式将输入的数值与实例中的值相加,并返回结果。
boolean compareAndSet(int expect, int update):
如果输入的值等于预期值,则以原子方式将该值设置为输入的值。
int getAndIncrement():
以原子的方式将当前值加 1
注意,这里返回的是自增前的值,也就是旧值。
void lazySet(int newValue):
最终会设置成newValue,使用lazySet设置值后,
可能导致其他线程在之后的一小段时间内还是可以读到旧的
int getAndSet(int newValue):
以原子的方式设置为newValue,并返回旧值
例
static AtomicInteger ai =new AtomicInteger(1);
public static void main(String[] args) {
System.out.println(ai.getAndIncrement());
System.out.println(ai.get());
}
getAndIncrement()实现原子操作示例分享
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
var5 = this.getIntVolatile(var1, var2);
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
return var5;
}
注意事项: AtomicBoolean将Boolean转成整型 然后使用compareAndSwapInt进行操作 /** * 如果当前数值是var4,则原子的将java变量更新成var5或var6 * @return 如果更新成功返回true */ public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5); public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5); public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);
原子更新数组
AtomicIntegerArray: 原子更新整型数组里的元素。 AtomicLongArray: 原子更新长整型数组里的元素。 AtomicReferenceArray: 原子更新引用类型数组里的元素。以上三个类常用的方法:
get(int index):获取索引为index的元素值。 compareAndSet(int i, int expect, int update): 如果当前值等于预期值,则以原子方式将数组位置 i 的元素设置为update值。
AtomicReferenceArray示例
static int[] value =new int[]{1,2};
static AtomicIntegerArray ai =new AtomicIntegerArray(value);
public static void main(String[] args) {
ai.getAndSet(0,2);
System.out.println(ai.get(0));
System.out.println(value[0]);
}
原子更新引用类型
原子更新基本类型的AtomicInteger 只能更新一个值 如果更新多个值 如更新一个对象里的值 则需使用原子更新引用类型提供的类
Atomic包包含以下三个类
AtomicReference:
原子更新引用类型
AtomicReferenceFieldUpdater:
原子更新引用类型的字段
AtomicMarkableReferce:
原子更新带有标记位的引用类型
可以使用构造方法更新一个布尔类型的标记位和引用类型。
public static AtomicReference<User> ai = new AtomicReference<User>();
public static void main(String[] args) {
User u1 = new User("java265", 22);
ai.set(u1);
User u2 = new User("liuliu", 19);
ai.compareAndSet(u1, u2);
System.out.println(ai.get().getAge() + ai.get().getName());
}
static class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
对象放于AtomicReference中 然后调用compareAndSet()原子操作替换 原理和 AtomicInteger相同 调用compareAndSwapObject()方法
原子更新字段类
当需要原子的更新类里某个字段时 需要用到原子更新字段类 Atomic包提供了3个类进行原子字段更新: AtomicIntegerFieldUpdater:原子更新整型的字段的更新器。 AtomicLongFieldUpdater:原子更新长整型字段的更新器。 AtomicStampedFieldUpdater:原子更新带有版本号的引用类型。例:
//创建原子更新器,并设置需要更新的对象类和对象的属性
private static AtomicIntegerFieldUpdater<User> ai = AtomicIntegerFieldUpdater.newUpdater(User.class, "age");
public static void main(String[] args) {
User u1 = new User("java265",22);
//原子更新年龄,+1
System.out.println(ai.getAndIncrement(u1));
System.out.println(u1.getAge());
}
static class User {
private String name;
public volatile int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
第一步:
因为原子更新字段类都是抽象类,每次使用的时候必须使用静态方法newUpdater()
创建一个更新器,并且需要设置想要更新的类和属性
第二步:
更新类的字段必须使用 public volatile 修饰
新增原子类简介
DoubleAccumulator LongAccumulator DoubleAdder LongAdder
LongAdder是LongAccumulator的一个特例
调用LongAdder相当使用下面的方式
调用LongAccumulator,LongAccumulator提供了比LongAdder更强大的功能
构造函数其中accumulatorFunction一个双目运算器接口
根据输入的两个参数返回一个计算值
identity则是LongAccumulator累加器的初始值
例:
private static ExecutorService executorService = Executors.newFixedThreadPool(5);
public static void main(String[] args) {
for (int i = 1; i <= 100; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
counter.add(2);
}
});
}
System.out.println(counter.sum());
System.out.println(counter);
}
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。


