Bootstrap

Java并发编程 原子 Atomic 基本类型 CountDownLatch阻塞 数组类型 原子类 AtomicIntegerArray 看源码自我学习

原子类

原子类

我们进行了分类

基本类型原子类

案例

50 个线程去加 100 次

输出的结果会小于等于 50000

import java.util.concurrent.atomic.AtomicInteger;

public class AtomicIntegerDemo {

    public static final int SIZE_=50;
    public static void main(String[] args) {
        MyNumber myNumber = new MyNumber();
        for(int i=1;i<=SIZE_;i++){
            new Thread(()->{
                for (int i1 = 0; i1 < 100; i1++) {
                    myNumber.addPlusPlus();
                }
            },String.valueOf(i)).start();
        }
        System.out.println(myNumber.number);
    }
}
// 资源类
class MyAtomicNumber{
    AtomicInteger atomicInteger=new AtomicInteger();
    public void addPlusPlus(){
        atomicInteger.incrementAndGet();
    }
}

输出

因为 main 线程太快了

还没算完

等所有线程执行结束再执行 main 线程

CountDownLatch 类阻塞

countDownLatch 会等线程完成一个后自减

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

public class AtomicIntegerDemo {

    public static final int SIZE_=50;
    public static void main(String[] args) throws InterruptedException {
        MyNumber myNumber = new MyNumber();
        CountDownLatch countDownLatch = new CountDownLatch(SIZE_);
        for(int i=1;i<=SIZE_;i++){
            new Thread(()->{
                try {
                    for (int i1 = 0; i1 < 100; i1++) {
                        myNumber.addPlusPlus();
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    countDownLatch.countDown();
                }
            },String.valueOf(i)).start();
        }
        countDownLatch.await();
        // 因为 main 线程太快了 会提前进入
        System.out.println(myNumber.number);
    }
}
// 资源类
class MyAtomicNumber{
    AtomicInteger atomicInteger=new AtomicInteger();
    public void addPlusPlus(){
        atomicInteger.incrementAndGet();
    }
}

相当于一个阻塞效果

敲了一个

代码

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicIntegerArray;

public class AtomicIntegerArrayDemo {
    public static void main(String[] args) {
        // 定义原子整型类型的数据
        AtomicInteger atomicInteger1 = new AtomicInteger(1);
        AtomicInteger atomicInteger2 = new AtomicInteger(2);
        AtomicInteger atomicInteger3 = new AtomicInteger(3);

        // 原子整型的数据 数组
//        AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(new int[]{1, 2, 3});

        // 创建一个长度为5的AtomicIntegerArray,初始值都为0
        AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(new int[5]);

        // 打印数组初始值
        for (int i = 0; i < atomicIntegerArray.length();  i++) {
            System.out.println(atomicIntegerArray.get(i));
        }

        int tmpInt = 0;
        // 将数组中索引为0的元素设置为1122,并返回原来的值
        tmpInt = atomicIntegerArray.getAndSet(0,  1122);
        System.out.println(tmpInt  + "\t" + atomicIntegerArray.get(0));

        // 对数组中索引为1的元素进行自增操作
        atomicIntegerArray.getAndIncrement(1);
        atomicIntegerArray.getAndIncrement(1);
        // 对数组中索引为1的元素进行自增操作,并返回原来的值
        tmpInt = atomicIntegerArray.getAndIncrement(1);
        System.out.println(tmpInt  + "\t" + atomicIntegerArray.get(1));
    }
    }
}

AtomicIntegerArray 类是 Java 并发包(java.util.concurrent.atomic )中的一个类,它提供了一种线程安全的方式来操作整数数组。与普通的整数数组不同,AtomicIntegerArray 提供的方法可以确保在多线程环境下的操作是原子的,即不会发生数据竞争或不一致的问题。

下面是一些关于 AtomicIntegerArray 类的相关代码示例及其解释:

创建 AtomicIntegerArray

你可以通过以下几种方式创建 AtomicIntegerArray 实例:

  1. 使用已有的整数数组:
java

复制
int[] array = {1, 2, 3, 4, 5};
AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(array);
  1. 指定数组长度,所有元素初始化为0:
java

复制
AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(5);
  1. 使用已有的整数数组并复制该数组:
java

复制
int[] array = {1, 2, 3, 4, 5};
AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(array.clone());

基本操作

AtomicIntegerArray 提供了一些基本的操作方法,如获取、设置、自增、自减等。以下是一些常见的操作示例:

  1. 获取指定索引处的值:
java

复制
int value = atomicIntegerArray.get(0); 
System.out.println("Value  at index 0: " + value);
  1. 设置指定索引处的值:
java

复制
atomicIntegerArray.set(0,  10);
System.out.println("New  value at index 0: " + atomicIntegerArray.get(0));
  1. 原子地设置指定索引处的值,并返回旧值:
java

复制
int oldValue = atomicIntegerArray.getAndSet(0,  20);
System.out.println("Old  value at index 0: " + oldValue);
  1. 原子地自增指定索引处的值:
java

复制
int incrementedValue = atomicIntegerArray.getAndIncrement(1); 
System.out.println("Incremented  value at index 1: " + incrementedValue);
  1. 原子地自减指定索引处的值:
java

复制
int decrementedValue = atomicIntegerArray.getAndDecrement(1); 
System.out.println("Decremented  value at index 1: " + decrementedValue);
  1. 原子地增加指定索引处的值,并返回旧值:
java

复制
int addedValue = atomicIntegerArray.getAndAdd(1,  5);
System.out.println("Added  value at index 1: " + addedValue);

CAS 操作

AtomicIntegerArray 还提供了一些基于比较并交换(Compare and Swap, CAS)的操作,这些操作可以确保在多线程环境下的原子性:

  1. 原子地设置指定索引处的值,只有当当前值等于预期值时才设置成功:
java

复制
boolean isSet = atomicIntegerArray.compareAndSet(0,  20, 30);
System.out.println("Is  set successful: " + isSet);

完整示例

以下是一个完整的示例,展示了如何使用 AtomicIntegerArray 类的各种方法:

java

复制
import java.util.concurrent.atomic.AtomicIntegerArray; 
 
public class AtomicIntegerArrayExample {
    public static void main(String[] args) {
        // 创建一个长度为5的AtomicIntegerArray,初始值都为0 
        AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(5);
 
        // 打印数组初始值 
        for (int i = 0; i < atomicIntegerArray.length();  i++) {
            System.out.println("Initial  value at index " + i + ": " + atomicIntegerArray.get(i)); 
        }
 
        // 设置指定索引处的值 
        atomicIntegerArray.set(0,  10);
        System.out.println("New  value at index 0: " + atomicIntegerArray.get(0)); 
 
        // 原子地设置指定索引处的值,并返回旧值 
        int oldValue = atomicIntegerArray.getAndSet(0,  20);
        System.out.println("Old  value at index 0: " + oldValue);
 
        // 原子地自增指定索引处的值 
        int incrementedValue = atomicIntegerArray.getAndIncrement(1); 
        System.out.println("Incremented  value at index 1: " + incrementedValue);
 
        // 原子地自减指定索引处的值 
        int decrementedValue = atomicIntegerArray.getAndDecrement(1); 
        System.out.println("Decremented  value at index 1: " + decrementedValue);
 
        // 原子地增加指定索引处的值,并返回旧值 
        int addedValue = atomicIntegerArray.getAndAdd(1,  5);
        System.out.println("Added  value at index 1: " + addedValue);
 
        // 原子地设置指定索引处的值,只有当当前值等于预期值时才设置成功 
        boolean isSet = atomicIntegerArray.compareAndSet(0,  20, 30);
        System.out.println("Is  set successful: " + isSet);
    }
}

通过这些示例,你可以看到 AtomicIntegerArray 类在多线程环境下的强大功能,它可以确保对数组的操作是原子的,从而避免数据竞争和不一致的问题。

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;