原子操作类
大约 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