Java多線程中的原子類屬性說明
什么是原子類
什么是原子類
一度認為原子是不可分割的最小單位,故原子類可以認為其操作都是不可分割
為什么要有原子類
對多線程訪問同一個變量,我們需要加鎖,而鎖是比較消耗性能的,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的原子更新性能進行優(yōu)化提升
- DoubleAccumulator、LongAccumulator 支持自定義運算
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); //自定義計算 int i1 = atomicIntegerArray.accumulateAndGet(0, 2, ((left, right) -> left > right ? left : right )); System.out.println(i1); } }
原子更新屬性
原子地更新某個類里的某個字段時,就需要使用原子更新字段類,Atomic包提供了以下4個類進行原子字段更新
AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicStampedReference、AtomicReferenceFieldUpdater
使用上述類的時候,必須遵循以下原則
- 字段必須是volatile類型的,在線程之間共享變量時保證立即可見
- 字段的描述類型是與調(diào)用者與操作對象字段的關(guān)系一致。
- 也就是說調(diào)用者能夠直接操作對象字段,那么就可以反射進行原子操作。
- 對于父類的字段,子類是不能直接操作的,盡管子類可以訪問父類的字段。
- 只能是實例變量,不能是類變量,也就是說不能加static關(guān)鍵字。
- 只能是可修改變量,不能使final變量,因為final的語義就是不可修改。
- 對于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)當前時間的簡單實例
這篇文章介紹了在jmeter的beanshell中用java獲取系統(tǒng)當前時間的簡單實例,有需要的朋友可以參考一下2013-09-09關(guān)于java String中intern的深入講解
這篇文章主要給大家介紹了關(guān)于java String中intern的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用java具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧2019-04-04SpringCloud Alibaba 基本開發(fā)框架搭建過程
這篇文章主要介紹了SpringCloud Alibaba 基本開發(fā)框架搭建過程,開發(fā)工具選用的idea,本文通過圖文實例相結(jié)合給大家分享搭建全過程,需要的朋友可以參考下2021-06-06SpringBoot集成企業(yè)微信開發(fā)的實現(xiàn)
本文將詳細介紹如何使用?Spring?Boot?集成企業(yè)微信開發(fā),通過企業(yè)微信?API?可以實現(xiàn)企業(yè)內(nèi)部的一些自動化業(yè)務(wù)流程,提高工作效率,感興趣的可以了解一下2023-07-07使用java?-jar修改SpringBoot中application.properties的配置項
這篇文章主要介紹了使用java?-jar修改SpringBoot中application.properties的配置項問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02