| 1、一度认为原子是不可分割的最小单位,故原子类可以认为其操作都是不可分割 |
| 2、对多线程访问同一个变量,我们需要加锁,而锁是比较消耗性能的,JDk1.5之后,新增的原子操作类提供了一种用法简单、性能高效、线程安全地更新一个变量的方式,这些类同样位于JUC包下的atomic包下,发展到JDk1.8,该包下共有17个类,囊括了原子更新基本类型、原子更新数组、原子更新属性、原子更新引用 |
| 3、1.8新增的原子类:DoubleAccumulator、DoubleAdder、LongAccumulator、LongAdder、Striped64 |
| 1、发展至JDk1.8,基本类型原子类有以下几个:AtomicBoolean、AtomicInteger、AtomicLong、DoubleAccumulator、DoubleAdder、LongAccumulator、LongAdder |
| 2、大致可以归为3类 |
| AtomicBoolean、AtomicInteger、AtomicLong 元老级的原子更新,方法几乎一模一样 |
| DoubleAdder、LongAdder 对Double、Long的原子更新性能进行优化提升 |
| DoubleAccumulator、LongAccumulator 支持自定义运算 |
| public class Demo1 { |
| |
| |
| private static AtomicInteger sum = new AtomicInteger(0); |
| |
| public static void inCreate() { |
| sum.incrementAndGet(); |
| } |
| |
| |
| public static void main(String[] args) { |
| for (int i = 0; i < 10; i++) { |
| new Thread(()->{ |
| for (int j = 0; j < 100; j++) { |
| inCreate(); |
| System.out.println(sum); |
| } |
| }).start(); |
| } |
| } |
| |
| } |
| 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()); |
| longAccumulator.accumulate(5L); |
| System.out.println(longAccumulator.get()); |
| } |
| |
| } |
| AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray |
| public class AtomicIntegerArrayDemo { |
| |
| public static void main(String[] args) { |
| |
| int[] arr = new int[]{5, 3, 4}; |
| |
| AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(arr); |
| |
| System.out.println(atomicIntegerArray.addAndGet(2, 8)); |
| |
| |
| int i = atomicIntegerArray.accumulateAndGet(0, 2, (left, right) -> |
| left * right |
| ); |
| System.out.println(i); |
| } |
| |
| } |
| 1、原子地更新某个类里的某个字段时,就需要使用原子更新字段类,Atomic包提供了以下4个类进行原子字段更新 |
| AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicStampedReference、AtomicReferenceFieldUpdater |
| 2、使用上述类的时候,必须遵循以下原则 |
| 字段必须是volatile类型的,在线程之间共享变量时保证立即可见 |
| 字段的描述类型是与调用者与操作对象字段的关系一致。 也就是说调用者能够直接操作对象字段,那么就可以反射进行原子操作 |
| 对于父类的字段,子类是不能直接操作的,尽管子类可以访问父类的字段 |
| 只能是实例变量,不能是类变量,也就是说不能加static关键字 |
| 只能是可修改变量,不能使final变量,因为final的语义就是不可修改 |
| 对于AtomicIntegerFieldUpdater和AtomicLongFieldUpdater只能修改int/long类型的字段,不能修改其包装 类型(Integer/Long) |
| 如果要修改包装类型就需要使用AtomicReferenceFieldUpdater |
| public class AtomicLongFieldUpdaterDemo { |
| |
| public static void main(String[] args) { |
| |
| AtomicLongFieldUpdater<Student> longFieldUpdater = AtomicLongFieldUpdater.newUpdater(Student.class, "id"); |
| Student xdclass = new Student(1L, "xdclass"); |
| |
| longFieldUpdater.compareAndSet(xdclass, 1L, 100L); |
| System.out.println("id="+xdclass.getId()); |
| |
| |
| AtomicReferenceFieldUpdater<Student, String> referenceFieldUpdater = AtomicReferenceFieldUpdater.newUpdater(Student.class, String.class, "name"); |
| referenceFieldUpdater.compareAndSet(xdclass, "xdclass", "wiggin"); |
| System.out.println("name="+xdclass.getName()); |
| } |
| |
| } |
| |
| |
| class Student{ |
| volatile long id; |
| volatile 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; |
| } |
| } |
| AtomicReference:用于对引用的原子更新 |
| AtomicMarkableReference:带版本戳的原子引用类型,版本戳为boolean类型 |
| AtomicStampedReference:带版本戳的原子引用类型,版本戳为int类型 |
| public class AtomicReferenceDemo { |
| |
| |
| public static void main(String[] args) { |
| AtomicReference<Student> studentAtomicReference = new AtomicReference<>(); |
| Student student = new Student(1L, "xdclass"); |
| Student student1 = new Student(2L, "wiggin"); |
| studentAtomicReference.set(student); |
| studentAtomicReference.compareAndSet(student, student1); |
| Student student2 = studentAtomicReference.get(); |
| System.out.println(student2.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; |
| } |
| } |
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术