• 多线程JUC 第2季 多线程的原子性


    一 多线程原子性

    1.1 基本数据类型原子

    atomicInteger, atomicLong,atomicBoolean

    1.代码countdownlatch

    1. package com.ljf.thread.atomic;
    2. import java.util.concurrent.CountDownLatch;
    3. import java.util.concurrent.atomic.AtomicInteger;
    4. class MyNumber
    5. {
    6. AtomicInteger atomicInteger = new AtomicInteger();
    7. public void addPlusPlus()
    8. {
    9. atomicInteger.getAndIncrement();
    10. }
    11. }
    12. /**
    13. * @ClassName: AtomicDemo
    14. * @Description: TODO
    15. * @Author: admin
    16. * @Date: 2023/11/06 22:24:14 
    17. * @Version: V1.0
    18. **/
    19. public class AtomicDemo {
    20. public static void main(String[] args) throws InterruptedException {
    21. MyNumber myNumber = new MyNumber();
    22. CountDownLatch ct=new CountDownLatch(10);
    23. for(int k=1;k<=10;k++){
    24. new Thread(new Runnable() {
    25. @Override
    26. public void run() {
    27. for(int k=0;k<30;k++){
    28. myNumber.addPlusPlus();
    29. }
    30. ct.countDown();
    31. }
    32. },String.valueOf(k)).start();
    33. }
    34. ct.await();
    35. System.out.println("");
    36. System.out.println(Thread.currentThread().getName()+"\t"+"result: "+myNumber.atomicInteger.get());
    37. }
    38. }

    结果:

    1.2 原子数组类型

    1.AtomicIntegerArray 2.AtomicLongArray  3. AtomicReferenceArray

    1.3 引用数据类型

    1.AtomicReference

    2.AtomicStampedReference  携带版本号的引用类,解决修改过几次

    3.AtomicMarkableReference  原子更新带有标记位 解决是否修改过  状态戳  true/false

    1.4 字段级别原子更新

    1.4.1 介绍作用

    1.AtomicIntegerFieldUpdater   原子更新对象中int类型字段的值

    2.AtomicLongFieldUpdater   原子更新对象中Long类型字段的值。

    3.AtomicReferenceFieldUpdater  原子更新引用数据类型字段的值

    目的:以一种线程安全的方式操作非线程安全的对象内的某些字段。更新的对象属性必须使用public volatile修饰符。因为对象的属性修改类型原子类都是抽象类,所有每次使用都必须使用静态方法newUpdate()方法创建一个更新器,并且需要设置想要更新的类和属性。 

    1.4.2 代码

    1.4.2.1 原始锁的方式

    1.原始锁方式

    1. public class AtomicDemo {
    2. public static void main(String[] args) throws InterruptedException {
    3. CountDownLatch countDownLatch=new CountDownLatch(10);
    4. PayInfo payInfo =new PayInfo();
    5. for(int k=0;k<10;k++){
    6. new Thread(()->{
    7. try {
    8. for (int m = 0; m < 1000; m++) {
    9. payInfo.add();
    10. //payInfo.transferMoney(payInfo);
    11. }
    12. }
    13. catch (Exception e){
    14. e.printStackTrace();
    15. }
    16. finally {
    17. countDownLatch.countDown();
    18. }
    19. }).start();
    20. }
    21. countDownLatch.await();
    22. System.out.println(Thread.currentThread().getName()+"\t"+payInfo.money);
    23. }
    24. }

    资源类

    1. public class PayInfo {
    2. String bankName = "icbc";
    3. int money = 0;
    4. // public volatile int money = 0;
    5. public synchronized void add(){
    6. money++;
    7. }
    8. // AtomicIntegerFieldUpdater<PayInfo> atomicIntegerFieldUpdater=AtomicIntegerFieldUpdater.newUpdater(PayInfo.class,"money");
    9. // public void transferMoney(PayInfo payInfo){
    10. // atomicIntegerFieldUpdater.getAndIncrement(payInfo);
    11. // }
    12. }

    3.结果

    1.4.2.2 字段级别的更新

    1.资源类

    1. public class PayInfo {
    2. String bankName = "icbc";
    3. // int money = 0;
    4. public volatile int money = 0;
    5. public synchronized void add(){
    6. money++;
    7. }
    8. AtomicIntegerFieldUpdater<PayInfo> atomicIntegerFieldUpdater=AtomicIntegerFieldUpdater.newUpdater(PayInfo.class,"money");
    9. public void transferMoney(PayInfo payInfo){
    10. atomicIntegerFieldUpdater.getAndIncrement(payInfo);
    11. }
    12. }

    2.代码

    1. public class AtomicDemo {
    2. public static void main(String[] args) throws InterruptedException {
    3. CountDownLatch countDownLatch=new CountDownLatch(10);
    4. PayInfo payInfo =new PayInfo();
    5. for(int k=0;k<10;k++){
    6. new Thread(()->{
    7. try {
    8. for (int m = 0; m < 1000; m++) {
    9. //payInfo.add();
    10. payInfo.transferMoney(payInfo);
    11. }
    12. }
    13. catch (Exception e){
    14. e.printStackTrace();
    15. }
    16. finally {
    17. countDownLatch.countDown();
    18. }
    19. }).start();
    20. }
    21. countDownLatch.await();
    22. System.out.println(Thread.currentThread().getName()+"\t"+payInfo.money);
    23. }
    24. }

    3.结果

    1.5 LongAdder与LongAccumlator

    1.5.1 介绍

    LongAdder 只能用来计算加法,且从零开始计算。

    LongAccumulator提供了自定义的函数操作。

    1.5.2 代码

    1. public class LongAdderDemo {
    2. public static void main(String[] args) {
    3. LongAdder longAdder=new LongAdder();
    4. longAdder.increment();
    5. longAdder.increment();
    6. System.out.println("result:"+longAdder.toString());
    7. LongAccumulator longAccumulator = new LongAccumulator(new LongBinaryOperator()
    8. {
    9. @Override
    10. public long applyAsLong(long left, long right)
    11. {
    12. System.out.println("left:"+left+" right:"+right);
    13. return left + right;
    14. }
    15. },9);
    16. longAccumulator.accumulate(1);//1
    17. longAccumulator.accumulate(3);//4
    18. System.out.println(longAccumulator.get());
    19. }
    20. }

    结果:

    1.6  四种原子操作计数的比较

    1.代码

    1. package com.ljf.thread.atomic;
    2. import java.util.concurrent.atomic.AtomicLong;
    3. import java.util.concurrent.atomic.LongAccumulator;
    4. import java.util.concurrent.atomic.LongAdder;
    5. /**
    6. * @ClassName: Clik
    7. * @Description: TODO
    8. * @Author: admin
    9. * @Date: 2023/12/24 10:51:07 
    10. * @Version: V1.0
    11. **/
    12. public class Clik {
    13. int number = 0;
    14. public synchronized void clickBySynchronized()
    15. {
    16. number++;
    17. }
    18. AtomicLong atomicLong = new AtomicLong(0);
    19. public void clickByAtomicLong()
    20. {
    21. atomicLong.getAndIncrement();
    22. }
    23. LongAdder longAdder = new LongAdder();
    24. public void clickByLongAdder()
    25. {
    26. longAdder.increment();
    27. }
    28. LongAccumulator longAccumulator = new LongAccumulator((x, y) -> x + y,0);
    29. public void clickByLongAccumulator()
    30. {
    31. longAccumulator.accumulate(1);
    32. }
    33. }

    2.调用类

    1. package com.ljf.thread.atomic;
    2. import java.util.concurrent.CountDownLatch;
    3. /**
    4. * @ClassName: AccumulatorCompareDemo
    5. * @Description: TODO
    6. * @Author: admin
    7. * @Date: 2023/12/24 10:51:51 
    8. * @Version: V1.0
    9. **/
    10. public class AccumulatorCompareDemo {
    11. public static final int _1W = 10000;
    12. public static final int threadNumber = 50;
    13. public static void main(String[] args) throws InterruptedException {
    14. long startTime;
    15. long endTime;
    16. Clik clik=new Clik();
    17. CountDownLatch countDownLatch1 = new CountDownLatch(threadNumber);
    18. CountDownLatch countDownLatch2 = new CountDownLatch(threadNumber);
    19. CountDownLatch countDownLatch3 = new CountDownLatch(threadNumber);
    20. CountDownLatch countDownLatch4 = new CountDownLatch(threadNumber);
    21. startTime = System.currentTimeMillis();
    22. for (int i = 1; i <=threadNumber; i++) {
    23. new Thread(() -> {
    24. try {
    25. for (int j = 1; j <=100 * _1W; j++) {
    26. clik.clickBySynchronized();
    27. }
    28. } finally {
    29. countDownLatch1.countDown();
    30. }
    31. },String.valueOf(i)).start();
    32. }
    33. countDownLatch1.await();
    34. endTime = System.currentTimeMillis();
    35. System.out.println("----costTime: "+(endTime - startTime) +" 毫秒"+"\t clickBySynchronized: "+clik.number);
    36. //
    37. startTime = System.currentTimeMillis();
    38. for (int i = 1; i <=threadNumber; i++) {
    39. new Thread(() -> {
    40. try {
    41. for (int j = 1; j <=100 * _1W; j++) {
    42. clik.clickByAtomicLong();
    43. }
    44. } finally {
    45. countDownLatch2.countDown();
    46. }
    47. },String.valueOf(i)).start();
    48. }
    49. countDownLatch2.await();
    50. endTime = System.currentTimeMillis();
    51. System.out.println("----costTime: "+(endTime - startTime) +" 毫秒"+"\t clickByAtomicLong: "+clik.number);
    52. //
    53. //
    54. //
    55. startTime = System.currentTimeMillis();
    56. for (int i = 1; i <=threadNumber; i++) {
    57. new Thread(() -> {
    58. try {
    59. for (int j = 1; j <=100 * _1W; j++) {
    60. clik.clickByLongAdder();
    61. }
    62. } finally {
    63. countDownLatch3.countDown();
    64. }
    65. },String.valueOf(i)).start();
    66. }
    67. countDownLatch3.await();
    68. endTime = System.currentTimeMillis();
    69. System.out.println("----costTime: "+(endTime - startTime) +" 毫秒"+"\t clickByLongAdder: "+clik.number);
    70. //
    71. startTime = System.currentTimeMillis();
    72. for (int i = 1; i <=threadNumber; i++) {
    73. new Thread(() -> {
    74. try {
    75. for (int j = 1; j <=100 * _1W; j++) {
    76. clik.clickByLongAccumulator();
    77. }
    78. } finally {
    79. countDownLatch4.countDown();
    80. }
    81. },String.valueOf(i)).start();
    82. }
    83. countDownLatch4.await();
    84. endTime = System.currentTimeMillis();
    85. System.out.println("----costTime: "+(endTime - startTime) +" 毫秒"+"\t clickByLongAccumulator: "+clik.number);
    86. }
    87. }

  • 相关阅读:
    uniapp中实现圆形进度条的方式有哪些?
    python——基础排坑+经验总结(持续更新)
    【WPF】Dispatcher 与消息循环
    24PL-18-50-1836、12PN-4.1-50-1836比例电磁铁控制器
    React 为什么使用map来渲染列表 而不是其他循环方法
    内省机制(操作javaBean的信息)
    C++内存管理
    微信公众号迁移详细步骤
    使用pydumpck反编译pyintaller生成的exe文件 python3.10
    【Vue3】vue3中组合式Api的setup写法快速入门上手起步
  • 原文地址:https://blog.csdn.net/u011066470/article/details/134255972