跳至主要內容

原子操作类

wangdx大约 9 分钟

简介


package com.yix.juc.atomic;

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

/**
 * @author wangdx
 */
public class Demo {
    public static int money = 0; // 模拟银行存款
    public static int moneyAsyn = 0; // 模拟银行存款
    public static AtomicInteger atomicInteger = new AtomicInteger(0); // 模拟银行存款

    public static void main(String[] args) throws InterruptedException {
        saveBaseMoney();
        saveAsynMoney();
        saveAtomicMoney();
    }

    public static synchronized void save(int m) {
        moneyAsyn += m; // 模拟存款
    }

    private static void saveAtomicMoney() throws InterruptedException {
        int[] data = new int[]{100, 200, 300}; // 要存款的总额
        for (int x = 0; x < data.length; x++) {    // 进行存款线程的配置
            final int temp = x; // 为内部类使用
            new Thread(() -> {
                try {
                    TimeUnit.MILLISECONDS.sleep(100); // 100毫秒延迟
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                atomicInteger.addAndGet(data[temp]); // 模拟存款
            }).start();
        }
        TimeUnit.SECONDS.sleep(2); // 等待2秒的时间
        System.out.println("【计算完成】最终的存款总额:" + atomicInteger);
    }

    private static void saveAsynMoney() throws InterruptedException {
        int[] data = new int[]{100, 200, 300}; // 要存款的总额
        for (int x = 0; x < data.length; x++) {    // 进行存款线程的配置
            final int temp = x; // 为内部类使用
            new Thread(() -> {
                try {
                    TimeUnit.MILLISECONDS.sleep(100); // 100毫秒延迟
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                save(data[temp]);
            }).start();
        }
        TimeUnit.SECONDS.sleep(2); // 等待2秒的时间
        System.out.println("【计算完成】最终的存款总额:" + moneyAsyn);
    }

    private static void saveBaseMoney() throws InterruptedException {
        int[] data = new int[]{100, 200, 300}; // 要存款的总额
        for (int x = 0; x < data.length; x++) {    // 进行存款线程的配置
            final int temp = x; // 为内部类使用
            new Thread(() -> {
                try {
                    TimeUnit.MILLISECONDS.sleep(100); // 100毫秒延迟
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                money += data[temp]; // 模拟存款
            }).start();
        }
        TimeUnit.SECONDS.sleep(2); // 等待2秒的时间
        System.out.println("【计算完成】最终的存款总额:" + money);
    }
}

基础原子类

1、
package com.yootk;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

public class YootkDemo { // 李兴华高薪就业编程训练营
    public static void main(String[] args) throws Exception { // 沐言科技:www.yootk.com
        AtomicLong num = new AtomicLong(0); // 实例化原子类对象
        for (int x = 0 ; x < 3 ; x ++) {
            new Thread(()->{
                System.out.printf("【%s】数据的加法计算:%d %n", Thread.currentThread().getName(), num.addAndGet(100));
            }).start();
        }
        TimeUnit.SECONDS.sleep(1); // 等待1秒的时间
        System.out.println("【计算完成】最终的计算结果为:" + num);
    }
}


2、
package com.yootk;

import java.util.concurrent.atomic.AtomicLong;

public class YootkDemo { // 李兴华高薪就业编程训练营
    public static void main(String[] args) throws Exception { // 沐言科技:www.yootk.com
        AtomicLong num = new AtomicLong(100L); // 实例化原子类对象
        System.err.println("【×原子数据修改】数据修改的结果:" + num.compareAndSet(200L, 300L));
        System.err.println("【×原子数据获取】新的数据内容:" + num.get());
        System.out.println("【√原子数据修改】数据修改的结果:" + num.compareAndSet(100L, 300L));
        System.out.println("【√原子数据获取】新的数据内容:" + num.get());
    }
}

数组原子

1、

package com.yootk;

import java.util.concurrent.atomic.AtomicReferenceArray;

public class YootkDemo { // 李兴华高薪就业编程训练营
    public static void main(String[] args) throws Exception { // 沐言科技:www.yootk.com
        String datas[] = new String[]{ "www.yootk.com", "edu.yootk.com",
                "muyan.yootk.com" }; // 定义一个字符串数组
        // 下面使用String数组来实现原子数组操作类对象的实例化处理
        AtomicReferenceArray<String> array = new AtomicReferenceArray<>(datas); // 获取原子类
        System.out.println("【原子数据修改】数据修改的结果:" + array.compareAndSet(2, "muyan.yootk.com", "book.yootk.com"));
        System.out.print("【原子数据获取】数组内容:");
        for (int x = 0; x < array.length(); x++) {
            System.out.print(array.get(x) + "、");
        }
    }
}

2、
package com.yootk;

import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.util.Arrays;

public class YootkDemo { // 李兴华高薪就业编程训练营
    public static void main(String[] args) throws Exception { // 沐言科技:www.yootk.com
        String datas[] = new String[]{"www.yootk.com", "edu.yootk.com",
                "muyan.yootk.com"}; // 定义一个字符串数组
        VarHandle varHandle = MethodHandles.arrayElementVarHandle(String[].class); // 获取VarHandle
        // 依然是CAS的处理方法,依然要通过CPU指令来执行相关的处理,性能是最高的
        varHandle.compareAndSet(datas, 2, "muyan.yootk.com", "book.yootk.com"); // 修改数据
        System.out.println(Arrays.toString(datas));
    }
}


3、

package com.yootk;

import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
class Book {
    String title; // 此时没有进行封装,因为封装了操作不了
}
public class YootkDemo { // 李兴华高薪就业编程训练营
    public static void main(String[] args) throws Exception { // 沐言科技:www.yootk.com
        // 此时通过类的查找机制找到Book类中的Title属性,同时设置好Title属性的对应的数据类型
        VarHandle varHandle = MethodHandles.lookup().findVarHandle(Book.class, "title", String.class);
        // 所有类的对象的属性操作前提就是要进行有效的对象实例化处理。
        Object obj = Book.class.getDeclaredConstructor().newInstance(); // 对象实例化
        varHandle.set(obj, "Java就业编程实战"); // 设置属性的内容
        System.out.println("【获取属性内容】title = " + varHandle.get(obj)); // 直接获取属性
    }
}

引用类型原子

1、
package com.yootk;

import java.util.concurrent.atomic.AtomicReference;

class Book {    // 自定义一个引用类
    private String title; // 名称
    private double price; // 价格
    public Book(String title, double price) {
        this.title = title;
        this.price = price;
    }
    @Override
    public String toString() {
        return "【图书】名称 = " + this.title + "、价格 = " + this.price;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
}
public class YootkDemo { // 李兴华高薪就业编程训练营
    public static void main(String[] args) throws Exception { // 沐言科技:www.yootk.com
        Book book = new Book("Java就业编程实战", 69.8); // 定义图书对象
        AtomicReference ref = new AtomicReference(book); // 原子引用
        ref.compareAndSet(book, new Book("Spring就业编程实战", 67.8)); // 数据更改
        System.out.println(ref);
    }
}


2、
package com.yootk;

import java.util.concurrent.atomic.AtomicReference;

class Book {    // 自定义一个引用类
    private String title; // 名称
    private double price; // 价格
    public Book(String title, double price) {
        this.title = title;
        this.price = price;
    }
    @Override
    public String toString() {
        return "【图书】名称 = " + this.title + "、价格 = " + this.price;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
}
public class YootkDemo { // 李兴华高薪就业编程训练营
    public static void main(String[] args) throws Exception { // 沐言科技:www.yootk.com
        // 此时的程序代码变为了一个匿名对象,直接存储的是一个匿名对象,没有栈内存的指向
        AtomicReference ref = new AtomicReference(new Book("Java就业编程实战", 69.8));
        ref.compareAndSet(new Book("Java就业编程实战", 69.8), new Book("Spring就业编程实战", 67.8)); // 数据更改
        System.out.println(ref);
    }
}


3、
package com.yootk;

import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;

class Book {    // 自定义一个引用类
    private String title; // 名称
    private double price; // 价格
    public Book(String title, double price) {
        this.title = title;
        this.price = price;
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Book book = (Book) o;
        return Double.compare(book.price, price) == 0 && title.equals(book.title);
    }
    @Override
    public int hashCode() {
        return Objects.hash(title, price);
    }
    @Override
    public String toString() {
        return "【图书】名称 = " + this.title + "、价格 = " + this.price;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
}
public class YootkDemo { // 李兴华高薪就业编程训练营
    public static void main(String[] args) throws Exception { // 沐言科技:www.yootk.com
        // 此时的程序代码变为了一个匿名对象,直接存储的是一个匿名对象,没有栈内存的指向
        AtomicReference ref = new AtomicReference(new Book("Java就业编程实战", 69.8));
        ref.compareAndSet(new Book("Java就业编程实战", 69.8), new Book("Spring就业编程实战", 67.8)); // 数据更改
        System.out.println(ref);
    }
}


4、
package com.yootk;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;

class Book {    // 自定义一个引用类
    private String title; // 名称
    private double price; // 价格
    public Book(String title, double price) {
        this.title = title;
        this.price = price;
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Book book = (Book) o;
        return Double.compare(book.price, price) == 0 && title.equals(book.title);
    }
    @Override
    public int hashCode() {
        return Objects.hash(title, price);
    }
    @Override
    public String toString() {
        return "【图书】名称 = " + this.title + "、价格 = " + this.price;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
}
public class YootkDemo { // 李兴华高薪就业编程训练营
    public static void main(String[] args) throws Exception { // 沐言科技:www.yootk.com
        Book book1 = new Book("Java就业编程实战", 69.8);
        Book book2 = new Book("Spring就业编程实战", 67.8);
        // 1是一个版本编号,按照正常的设计来讲,每一次修改之后版本编号一般都需要增加1
        AtomicStampedReference<Book> ref = new AtomicStampedReference<>(book1, 1);
        // 现在保存的版本号是1,但是此时匹配的版本号是3,那么版本号不匹配,无法进行内容的修改
        System.err.println("【×引用内容修改】" + ref.compareAndSet(book1, book2, 3, 5));
        System.err.println("【×原子引用数据】版本戳:" + ref.getStamp() + "、存储内容:" + ref.getReference());
        System.out.println("【√引用内容修改】" + ref.compareAndSet(book1, book2, 1, 2));
        System.out.println("【√原子引用数据】版本戳:" + ref.getStamp() + "、存储内容:" + ref.getReference());
    }
}


5、
package com.yootk;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicMarkableReference;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;

class Book {    // 自定义一个引用类
    private String title; // 名称
    private double price; // 价格
    public Book(String title, double price) {
        this.title = title;
        this.price = price;
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Book book = (Book) o;
        return Double.compare(book.price, price) == 0 && title.equals(book.title);
    }
    @Override
    public int hashCode() {
        return Objects.hash(title, price);
    }
    @Override
    public String toString() {
        return "【图书】名称 = " + this.title + "、价格 = " + this.price;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
}
public class YootkDemo { // 李兴华高薪就业编程训练营
    public static void main(String[] args) throws Exception { // 沐言科技:www.yootk.com
        Book book1 = new Book("Java就业编程实战", 69.8);
        Book book2 = new Book("Spring就业编程实战", 67.8);
        AtomicMarkableReference<Book> ref = new AtomicMarkableReference<>(book1, true);
        // 在数据修改之前首先要进行当前标记状态的判断,此时的状态标记不符合要求,所以一定无法修改成功
        System.err.println("【×引用内容修改】" + ref.compareAndSet(book1, book2, false, true));
        System.err.println("【×原子引用数据】标记:" + ref.isMarked() + "、存储内容:" + ref.getReference());
        System.out.println("【√引用内容修改】" + ref.compareAndSet(book1, book2, true, false));
        System.out.println("【√原子引用数据】标记:" + ref.isMarked() + "、存储内容:" + ref.getReference());
    }
}

属性原子

1、
package com.yootk;

import java.util.concurrent.atomic.AtomicLongFieldUpdater;
class Book {
    volatile long id; // 图书的编号,使用long类型
}
public class YootkDemo { // 李兴华高薪就业编程训练营
    public static void main(String[] args) throws Exception { // 沐言科技:www.yootk.com
        AtomicLongFieldUpdater updater = AtomicLongFieldUpdater.newUpdater(Book.class, "id");
        System.out.println(updater.getClass());
    }
}


2、
package com.yootk;

import java.util.concurrent.atomic.AtomicLongFieldUpdater;
class Book {
    // 此时的属性如果要想使用原子属性修改器,则必须使用volatiel关键字定义,否则执行时会出现如下的错误
    //  java.lang.IllegalArgumentException: Must be volatile type
    private volatile long id; // 图书的编号,使用long类型
    private String title; // 这些是不需要同步的属性
    private double price; // 这些是不需要同步的属性
    public Book(long id, String title, double price) {
        this.id = id;
        this.title = title;
        this.price = price;
    }

    public void setId(long id) { // 这个时候的id是需要进行同步处理的
        AtomicLongFieldUpdater updater = AtomicLongFieldUpdater.newUpdater(Book.class, "id");
        updater.compareAndSet(this, this.id, id); // CAS的修改操作
    }

    @Override
    public String toString() {
        return "【图书】ID = " + this.id + "、名称 = " + this.title + "、价格 = " + this.price;
    }
}
public class YootkDemo { // 李兴华高薪就业编程训练营
    public static void main(String[] args) throws Exception { // 沐言科技:www.yootk.com
        Book book = new Book(1002, "Java就业编程实战", 69.8); // 实例化Book类对象
        book.setId(6609); // 修改属性的内容
        System.out.println(book);
    }
}

并发计算

1、
package com.yootk;

import java.util.concurrent.atomic.DoubleAccumulator;

public class YootkDemo { // 李兴华高薪就业编程训练营
    public static void main(String[] args) throws Exception { // 沐言科技:www.yootk.com
        DoubleAccumulator da = new DoubleAccumulator((x, y) -> x + y, 1.1); // 每次增长1.1数据
        System.out.println("【累加器】原始存储内容:" + da.doubleValue());
        da.accumulate(20); // 数据累加计算
        System.out.println("【累加器】新的存储内容:" + da.doubleValue());
    }
}


2、
package com.yootk;

import java.util.concurrent.atomic.DoubleAdder;

public class YootkDemo { // 李兴华高薪就业编程训练营
    public static void main(String[] args) throws Exception { // 沐言科技:www.yootk.com
        DoubleAdder da = new DoubleAdder(); // 定义加法器
        // double和long都属于64位的数据,所以计算的时候需要考虑到2个32位数据的统一问题
        da.add(10);
        da.add(20);
        da.add(30);
        System.out.println("【加法器】计算结果:" + da.doubleValue());
    }
}

demo


上次编辑于: