Java多線程中的原子類屬性說明
什么是原子類
什么是原子類
一度認(rèn)為原子是不可分割的最小單位,故原子類可以認(rèn)為其操作都是不可分割
為什么要有原子類
對多線程訪問同一個變量,我們需要加鎖,而鎖是比較消耗性能的,JDk1.5之后,新增的原子操作類提供了一種用法簡單、性能高效、線程安全地更新一個變量的方式,這些類同樣位于JUC包下的atomic包下,發(fā)展到JDk1.8,該包下共有17個類,囊括了原子更新基本類型、原子更新數(shù)組、原子更新屬性、原子更新引用
java8新增原子類
DoubleAccumulator、DoubleAdder、LongAccumulator、LongAdder、Striped64
package 多線程.atomic.demo1;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @Author: ruan
* Date: 2021/7/4 12:09
* @Description:
*/
public class Demo1 {
private static AtomicInteger sum = new AtomicInteger(0);
public static void inCreat(){
sum.incrementAndGet();
}
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 10; i++) {
new Thread(()->{
for (int j = 0; j < 100; j++) {
inCreat();
System.out.println(sum);
try {
Thread.sleep(200l);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
}
原子更新基本類型
發(fā)展至JDk1.8,基本類型原子類有以下幾個:
AtomicBoolean、AtomicInteger、AtomicLong、DoubleAccumulator、DoubleAdder、LongAccumulator、LongAdder
大致可以歸為3類
- AtomicBoolean、AtomicInteger、AtomicLong 元老級的原子更新,方法幾乎一模一樣
- DoubleAdder、LongAdder 對Double、Long的原子更新性能進(jìn)行優(yōu)化提升
- DoubleAccumulator、LongAccumulator 支持自定義運(yùn)算
package 多線程.atomic.demo1;
import java.util.concurrent.atomic.LongAccumulator;
/**
* @Author: ruan
* Date: 2021/7/4 12:20
* @Description:
*/
public class Demo2 {
public static void main(String[] args) {
LongAccumulator longAccumulator = new LongAccumulator((left,right)->
left > right ? left : right,0L
);
longAccumulator.accumulate(3l);
System.out.println(longAccumulator.get());
}
}
原子更新數(shù)組類型
AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray
package 多線程.atomic.demo2;
import java.util.concurrent.atomic.AtomicIntegerArray;
/**
* @Author: ruan
* Date: 2021/7/4 12:26
* @Description:
*/
public class Demo1 {
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5};
AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(arr);
int i = atomicIntegerArray.addAndGet(1, 2);
System.out.println(i);
//自定義計(jì)算
int i1 = atomicIntegerArray.accumulateAndGet(0, 2, ((left, right) ->
left > right ? left : right
));
System.out.println(i1);
}
}
原子更新屬性
原子地更新某個類里的某個字段時,就需要使用原子更新字段類,Atomic包提供了以下4個類進(jìn)行原子字段更新
AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicStampedReference、AtomicReferenceFieldUpdater
使用上述類的時候,必須遵循以下原則
- 字段必須是volatile類型的,在線程之間共享變量時保證立即可見
- 字段的描述類型是與調(diào)用者與操作對象字段的關(guān)系一致。
- 也就是說調(diào)用者能夠直接操作對象字段,那么就可以反射進(jìn)行原子操作。
- 對于父類的字段,子類是不能直接操作的,盡管子類可以訪問父類的字段。
- 只能是實(shí)例變量,不能是類變量,也就是說不能加static關(guān)鍵字。
- 只能是可修改變量,不能使final變量,因?yàn)閒inal的語義就是不可修改。
- 對于AtomicIntegerFieldUpdater和AtomicLongFieldUpdater只能修改int/long類型的字段,不能修改其包裝類型(Integer/Long)。
- 如果要修改包裝類型就需要使用AtomicReferenceFieldUpdater。
package 多線程.atomic.demo3;
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
/**
* @Author: ruan
* Date: 2021/7/4 12:48
* @Description:
*/
public class Demo1 {
public static void main(String[] args) {
Student student = new Student("ruan", 18L);
AtomicLongFieldUpdater<Student> longFieldUpdater = AtomicLongFieldUpdater.newUpdater(Student.class, "age");
longFieldUpdater.compareAndSet(student,18L,20L);
System.out.println("age = " + student.getAge());
AtomicReferenceFieldUpdater<Student, String> objectObjectAtomicReferenceFieldUpdater = AtomicReferenceFieldUpdater.newUpdater(Student.class,String.class,"name");
objectObjectAtomicReferenceFieldUpdater.compareAndSet(student,"ruan","ruanxiangge");
System.out.println("name = " + student.getName());
}
}
class Student{
volatile String name;
volatile long age;
public Student(String name, long age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getAge() {
return age;
}
public void setAge(long age) {
this.age = age;
}
}
原子更新引用
- AtomicReference:用于對引用的原子更新
- AtomicMarkableReference:帶版本戳的原子引用類型,版本戳為boolean類型。
- AtomicStampedReference:帶版本戳的原子引用類型,版本戳為int類型。
package 多線程.atomic.demo4;
import java.util.concurrent.atomic.AtomicReference;
/**
* @Author: ruan
* Date: 2021/7/4 13:03
* @Description:
*/
public class Demo1 {
public static void main(String[] args) {
AtomicReference<Student> studentAtomicReference = new AtomicReference<>();
Student ruan = new Student(1L, "ruan");
Student rxg = new Student(2L, "rxg");
studentAtomicReference.set(ruan );
boolean b = studentAtomicReference.compareAndSet(ruan, rxg);
Student student = studentAtomicReference.get();
System.out.println(student.getName());
}
}
class Student{
private long id;
private 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;
}
}
到此這篇關(guān)于Java多線程中的原子類屬性說明的文章就介紹到這了,更多相關(guān)Java原子類屬性內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
在jmeter的beanshell中用java獲取系統(tǒng)當(dāng)前時間的簡單實(shí)例
這篇文章介紹了在jmeter的beanshell中用java獲取系統(tǒng)當(dāng)前時間的簡單實(shí)例,有需要的朋友可以參考一下2013-09-09
java實(shí)現(xiàn)雷霆戰(zhàn)機(jī)
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)雷霆戰(zhàn)機(jī),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-06-06
關(guān)于java String中intern的深入講解
這篇文章主要給大家介紹了關(guān)于java String中intern的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
SpringCloud Alibaba 基本開發(fā)框架搭建過程
這篇文章主要介紹了SpringCloud Alibaba 基本開發(fā)框架搭建過程,開發(fā)工具選用的idea,本文通過圖文實(shí)例相結(jié)合給大家分享搭建全過程,需要的朋友可以參考下2021-06-06
SpringBoot集成企業(yè)微信開發(fā)的實(shí)現(xiàn)
本文將詳細(xì)介紹如何使用?Spring?Boot?集成企業(yè)微信開發(fā),通過企業(yè)微信?API?可以實(shí)現(xiàn)企業(yè)內(nèi)部的一些自動化業(yè)務(wù)流程,提高工作效率,感興趣的可以了解一下2023-07-07
使用java?-jar修改SpringBoot中application.properties的配置項(xiàng)
這篇文章主要介紹了使用java?-jar修改SpringBoot中application.properties的配置項(xiàng)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02

