• JUC并发包下


    1.原子整数

      * AtomicBoolean

      * AtomicInteger

      * AtomicLong

    以AtomicInteger为例:

    1. public class test {
    2. public static void main(String[] args) throws InterruptedException {
    3. AtomicInteger i = new AtomicInteger(0);
    4. //获取并自增(i= 0,结果i = 1,返回0),类似于i++
    5. System.out.println(i.getAndIncrement());
    6. //自增并获取(i = 1,结果 i =2;返回2);类似于 ++i
    7. System.out.println(i.incrementAndGet());
    8. //自减并获取(i=2,结果 i = 1,返回 1 ),类似于--i
    9. System.out.println(i.decrementAndGet());
    10. //获取并自减(i=1,结果 i = 0,返回 1 ),类似于i--
    11. System.out.println(i.getAndDecrement());
    12. //获取并加值(i=0,结果i=5,返回0),类似于 i += 5;
    13. System.out.println(i.getAndAdd(5));
    14. i.updateAndGet(new IntUnaryOperator() {
    15. @Override
    16. public int applyAsInt(int value) {
    17. value = value*10;
    18. return value;
    19. }
    20. });
    21. }
    22. }

    2.原子引用

    * AtomicReference

    * AtomicMarkableReference

    * AtomicStampedReference

    1. public class test {
    2. public static void main(String[] args) throws InterruptedException {
    3. DecimalAccount.demo(new DecimalAccountCas(new BigDecimal("10000")));
    4. }
    5. }
    6. class DecimalAccountCas implements DecimalAccount{
    7. private AtomicReference balance; //范型中就是要保护的类型
    8. public DecimalAccountCas(BigDecimal balance) {
    9. this.balance = new AtomicReference<>(balance);
    10. }
    11. @Override
    12. public BigDecimal getBalance() {
    13. return balance.get();
    14. }
    15. @Override
    16. public void withdraw(BigDecimal amount) {
    17. while (true){
    18. BigDecimal pre = balance.get();
    19. BigDecimal next = pre.subtract(amount); //减去amount
    20. if (balance.compareAndSet(pre,next)){
    21. break;
    22. }
    23. }
    24. }
    25. }
    26. interface DecimalAccount{
    27. //获取余额
    28. BigDecimal getBalance();
    29. //取款
    30. void withdraw(BigDecimal amount);
    31. /*
    32. * 方法内会启动1000个线程,每个线程做 -10元操作,
    33. * 如果初始余额为10000 那么正确的结果为0
    34. * */
    35. static void demo(DecimalAccount account){
    36. ArrayList ts = new ArrayList<>();
    37. for (int i = 0; i < 1000; i++) {
    38. ts.add(new Thread(() -> {
    39. account.withdraw(BigDecimal.TEN);
    40. }));
    41. }
    42. ts.forEach(Thread :: start);
    43. ts.forEach(t -> {
    44. try {
    45. t.join();
    46. } catch (InterruptedException e) {
    47. e.printStackTrace();
    48. }
    49. });
    50. System.out.println(account.getBalance());
    51. }
    52. }

    AtomicStampedReference

    AtomicReference会有一个问题(cas),cas会有ABA问题。

    所以AtomicStampedReference就多了一个版本号来解决这个问题。

     

    AtomicStampedReference可以给原子引用加上版本号,追踪原子引用整个的变化过程,如:A -> B -> A -> C,通过AtomicStampedReference,我们可以知道引用变量中途被更改了几次。

    但是有时候,并不关心引用变量更改了几次,只是单纯的关心是否更改过,所以就有了AtomicMarkableReference

     AtomicMarkableReference

     3.原子数组

     

    之前的原子引用保护的是多个线程对一个对象引用进行修改时的线程安全性。像之前的

    ref这个保护的是BigDecimal,

     这里获取新的值,和变化以后的值。最后ref调用compeareAndSet变化的引用本身,变化成功就是next那个引用。

    但是有时候我们有时候并不是想修改引用本身而是想修改对象里面的内容,例如:数组(要对数组里面的元素保证线程安全)

    *  AtomicIntegerArray(保护的数组里面元素是整型的)

     AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(10);

    * AtomicLongArray(保护的数组里面元素是长整型的)

    * AtomicReferenceArray(保护的数组里面元素是引用类型的)

    4.原子字段更新器

    * AtomicReferenceFieldUpdater  //保护的是对象里面某个引用类型的字段

    * AtomicIntegerFieldUpdater

    * AtomicLongFieldUpdater

     

    5.原子累加器 

    AtomicInteger做累加的效率没有AtomicAdder的高。

     即AtomicInteger对一个变量累加,而AtomicAdder是对多个变量累加。

  • 相关阅读:
    如何处理Vue2项目里大规模的数据计算?
    数据结构——排序算法——桶排序
    FLUENT网格质量
    【Java SE】数据类型与变量
    蓝桥杯(3.15 刷真题)
    Java基础(第五期): 一维数组 && 二维数组 && 数组 && 引用数据类型在内存中的存储图解
    编译器优化丨Cache优化
    【用户画像】功能实现值写入ClickHouse人群包、预估和更新分群人数,NoSQL数据库介绍
    MySQL配置
    [山东科技大学OJ]1216 Problem D: 编写函数:字符串的复制 之二 (Append Code)
  • 原文地址:https://blog.csdn.net/weixin_54401017/article/details/126931747