Java 原子操作类

一、原子类

1.1 基本原子类

  • AtomicBoolean
  • AtomicInteger
  • AtomicLong

1.1.1 常用API

  1. public final int get() //获取当前的值
  2. public final int getAndSet(int newValue)//获取当前的值,并设置新的值
  3. public final int getAndIncrement()//获取当前的值,并自增
  4. public final int getAndDecrement() //获取当前的值,并自减
  5. public final int getAndAdd(int delta) //获取当前的值,并加上预期的值
  6. boolean compareAndSet(int expect, int update) //如果输入的数值等于预期值,则以原子方式将该值设置为输入值(update)

1.1.2 基本使用

public class AtomicIntegerDemo {public static final int SIEZ_ = 50;public static void main(String[] args) throws InterruptedException {AtomicInteger atomicInteger = new AtomicInteger();CountDownLatch countDownLatch = new CountDownLatch(SIEZ_);for (int i = 1; i <=SIEZ_; i++) {new Thread(() -> {try {for (int j = 1 ;j <=1000; j++) {atomicInteger.incrementAndGet();}}catch (Exception e){e.printStackTrace();}finally {countDownLatch.countDown();}},String.valueOf(i)).start();}countDownLatch.await();System.out.println(Thread.currentThread().getName()+"\t"+"---result : "+atomicInteger.get());}
}

1.2 数组类型原子类

  • AtomicIntegerArray
  • AtomicLongArray
  • AtomicReferenceArray

1.2.1 基本使用

public class AtomicIntegerArrayDemo {public static void main(String[] args) {AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(new int[5]);//AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(5);//AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(new int[]{1,2,3,4,5});for (int i = 0; i <atomicIntegerArray.length(); i++) {System.out.println(atomicIntegerArray.get(i));}System.out.println();System.out.println();System.out.println();int tmpInt = 0;tmpInt = atomicIntegerArray.getAndSet(0,1122);System.out.println(tmpInt+"\t"+atomicIntegerArray.get(0));atomicIntegerArray.getAndIncrement(1);atomicIntegerArray.getAndIncrement(1);tmpInt = atomicIntegerArray.getAndIncrement(1);System.out.println(tmpInt+"\t"+atomicIntegerArray.get(1));}
}

1.3 引用类型原子类

  • AtomicReference

1.3.1 AtomicReference基本使用

public class AtomicReferenceDemo
{public static void main(String[] args){User z3 = new User("z3",24);User li4 = new User("li4",26);AtomicReference<User> atomicReferenceUser = new AtomicReference<>();atomicReferenceUser.set(z3);System.out.println(atomicReferenceUser.compareAndSet(z3,li4)+"\t"+atomicReferenceUser.get().toString());System.out.println(atomicReferenceUser.compareAndSet(z3,li4)+"\t"+atomicReferenceUser.get().toString());}
}

 AtomicReference实现自旋锁

public class SpinLockDemo{AtomicReference<Thread> atomicReference = new AtomicReference<>();public void myLock(){Thread thread = Thread.currentThread();System.out.println(Thread.currentThread().getName()+"\t come in");while(!atomicReference.compareAndSet(null,thread)){}}public void myUnLock(){Thread thread = Thread.currentThread();atomicReference.compareAndSet(thread,null);System.out.println(Thread.currentThread().getName()+"\t myUnLock over");}public static void main(String[] args){SpinLockDemo spinLockDemo = new SpinLockDemo();new Thread(() -> {spinLockDemo.myLock();//暂停一会儿线程try { TimeUnit.SECONDS.sleep( 5 ); } catch (InterruptedException e) { e.printStackTrace(); }spinLockDemo.myUnLock();},"A").start();//暂停一会儿线程,保证A线程先于B线程启动并完成try { TimeUnit.SECONDS.sleep( 1 ); } catch (InterruptedException e) { e.printStackTrace(); }new Thread(() -> {spinLockDemo.myLock();spinLockDemo.myUnLock();},"B").start();}
}
  • AtomicStampedReference

AtomicStampedReference是携带版本号的引用类型原子类,可以解决ABA问题。解决修改过几次

1.3.2 AtomicStampedReference基本使用

    static AtomicInteger atomicInteger = new AtomicInteger(100);static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(100,1);public static void main(String[] args) {new Thread(() -> {int stamp = atomicStampedReference.getStamp();System.out.println(Thread.currentThread().getName()+"\t"+"---默认版本号: "+stamp);//让后面的t4获得和t3一样的版本号,都是1,好比较try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }atomicStampedReference.compareAndSet(100,101,stamp,stamp+1);System.out.println(Thread.currentThread().getName()+"\t"+"---1次版本号: "+atomicStampedReference.getStamp());atomicStampedReference.compareAndSet(101,100,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1);System.out.println(Thread.currentThread().getName()+"\t"+"---2次版本号: "+atomicStampedReference.getStamp());},"t3").start();new Thread(() -> {int stamp = atomicStampedReference.getStamp();System.out.println(Thread.currentThread().getName()+"\t"+"---默认版本号: "+stamp);//上前面的t3完成ABA问题try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }boolean result = atomicStampedReference.compareAndSet(100, 20210308, stamp, stamp + 1);System.out.println(Thread.currentThread().getName()+"\t"+"---操作成功否:"+result+"\t"+atomicStampedReference.getStamp()+"\t"+atomicStampedReference.getReference());},"t4").start();}
  • AtomicMarkableReference

原子更新带有标记位的引用类型对象 。只关心是否被修改过

1.3.3 AtomicMarkableReference基本使用

public class ABADemo{static AtomicInteger atomicInteger = new AtomicInteger(100);static AtomicStampedReference<Integer> stampedReference = new AtomicStampedReference<>(100,1);static AtomicMarkableReference<Integer> markableReference = new AtomicMarkableReference<>(100,false);public static void main(String[] args){new Thread(() -> {atomicInteger.compareAndSet(100,101);atomicInteger.compareAndSet(101,100);System.out.println(Thread.currentThread().getName()+"\t"+"update ok");},"t1").start();new Thread(() -> {//暂停几秒钟线程try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }atomicInteger.compareAndSet(100,2020);},"t2").start();//暂停几秒钟线程try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }System.out.println(atomicInteger.get());System.out.println();System.out.println();System.out.println();System.out.println("============以下是ABA问题的解决,让我们知道引用变量中途被更改了几次=========================");new Thread(() -> {System.out.println(Thread.currentThread().getName()+"\t 1次版本号"+stampedReference.getStamp());//故意暂停200毫秒,让后面的t4线程拿到和t3一样的版本号try { TimeUnit.MILLISECONDS.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); }stampedReference.compareAndSet(100,101,stampedReference.getStamp(),stampedReference.getStamp()+1);System.out.println(Thread.currentThread().getName()+"\t 2次版本号"+stampedReference.getStamp());stampedReference.compareAndSet(101,100,stampedReference.getStamp(),stampedReference.getStamp()+1);System.out.println(Thread.currentThread().getName()+"\t 3次版本号"+stampedReference.getStamp());},"t3").start();new Thread(() -> {int stamp = stampedReference.getStamp();System.out.println(Thread.currentThread().getName()+"\t =======1次版本号"+stamp);//暂停2秒钟,让t3先完成ABA操作了,看看自己还能否修改try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }boolean b = stampedReference.compareAndSet(100, 2020, stamp, stamp + 1);System.out.println(Thread.currentThread().getName()+"\t=======2次版本号"+stampedReference.getStamp()+"\t"+stampedReference.getReference());},"t4").start();System.out.println();System.out.println();System.out.println();System.out.println("============AtomicMarkableReference不关心引用变量更改过几次,只关心是否更改过======================");new Thread(() -> {boolean marked = markableReference.isMarked();System.out.println(Thread.currentThread().getName()+"\t 1次版本号"+marked);try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); }markableReference.compareAndSet(100,101,marked,!marked);System.out.println(Thread.currentThread().getName()+"\t 2次版本号"+markableReference.isMarked());markableReference.compareAndSet(101,100,markableReference.isMarked(),!markableReference.isMarked());System.out.println(Thread.currentThread().getName()+"\t 3次版本号"+markableReference.isMarked());},"t5").start();new Thread(() -> {boolean marked = markableReference.isMarked();System.out.println(Thread.currentThread().getName()+"\t 1次版本号"+marked);//暂停几秒钟线程try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); }markableReference.compareAndSet(100,2020,marked,!marked);System.out.println(Thread.currentThread().getName()+"\t"+markableReference.getReference()+"\t"+markableReference.isMarked());},"t6").start();}
}

1.4 对象的属性修改原子类

  • AtomicIntegerFieldUpdater  

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

  • AtomicLongFieldUpdater

        原子更新对象中Long类型字段的值

  • AtomicReferenceFieldUpdater

        原子更新引用类型字段的值

1.4.1 作用

        以一种线程安全的方式操作非线程安全对象内的某些字段

1.4.2 使用要求

  • 更新的对象属性必须使用 public volatile 修饰符。
  • 因为对象的属性修改类型原子类都是抽象类,所以每次使用都必须使用静态方法newUpdater()创建一个更新器,并且需要设置想要更新的类和属性。

1.4.3 基本使用

  • AtomicIntegerFieldUpdaterDemo
class BankAccount
{String bankName = "boc";//以一种线程安全的方式操作非线程安全对象内的某些字段//1 更新的对象属性必须使用 public volatile 修饰符。public volatile int money = 0;//2 因为对象的属性修改类型原子类都是抽象类,所以每次使用都必须// 使用静态方法newUpdater()创建一个更新器,并且需要设置想要更新的类和属性。AtomicIntegerFieldUpdater FieldUpdater = AtomicIntegerFieldUpdater.newUpdater(BankAccount.class,"money");public void transfer(BankAccount bankAccount){FieldUpdater.incrementAndGet(bankAccount);}
}/*** 以一种线程安全的方式操作非线程安全对象的某些字段。* 需求:* 1000个人同时向一个账号转账一元钱,那么累计应该增加1000元,* 除了synchronized和CAS,还可以使用AtomicIntegerFieldUpdater来实现。*/
public class AtomicIntegerFieldUpdaterDemo
{public static void main(String[] args) throws InterruptedException{BankAccount bankAccount = new BankAccount();CountDownLatch countDownLatch = new CountDownLatch(1000);for (int i = 1; i <=1000; i++) {new Thread(() -> {bankAccount.transfer(bankAccount);countDownLatch.countDown();},String.valueOf(i)).start();}countDownLatch.await();System.out.println(Thread.currentThread().getName()+"\t"+"---bankAccount: "+bankAccount.money);}
}
  • AtomicReferenceFieldUpdater
class MyVar {public volatile Boolean isInit = Boolean.FALSE;AtomicReferenceFieldUpdater<MyVar,Boolean> FieldUpdater = AtomicReferenceFieldUpdater.newUpdater(MyVar.class,Boolean.class,"isInit");public void init(MyVar myVar) {if(FieldUpdater.compareAndSet(myVar,Boolean.FALSE,Boolean.TRUE)){System.out.println(Thread.currentThread().getName()+"\t"+"---start init");try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }System.out.println(Thread.currentThread().getName()+"\t"+"---end init");}else{System.out.println(Thread.currentThread().getName()+"\t"+"---抢夺失败,已经有线程在修改中");}}}/***  多线程并发调用一个类的初始化方法,如果未被初始化过,将执行初始化工作,要求只能初始化一次*/
public class AtomicReferenceFieldUpdaterDemo {public static void main(String[] args) {MyVar myVar = new MyVar();for (int i = 1; i <=5; i++) {new Thread(() -> {myVar.init(myVar);},String.valueOf(i)).start();}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/194614.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

游泳馆会员服务预约管理系统预约小程序效果如何

游泳馆在各地每天都有大量用户前往&#xff0c;夏季室外、冬季室内也是学习游泳技术和休闲娱乐的好地方&#xff0c;而消费者大多是年轻人和家长带的孩子&#xff0c;这部分群体更显年轻化&#xff0c;因此在如今互联网环境下&#xff0c;传统商家需要进一步赋能客户消费路径。…

【Vue】Vue CLI 脚手架(Vue Command Line Interface)安装教程(通过npm)

前言 Vue CLI&#xff08;Vue Command Line Interface&#xff09;是一个基于Vue.js的官方脚手架工具&#xff0c;用于快速搭建和管理Vue.js项目。它提供了一套完整的开发工具和配置&#xff0c;包括项目初始化、开发服务器、热重载、构建和打包等功能。 Vue CLI使用了Webpac…

Doris 数据导出方式总结

1 Export导出 数据导出是Doris提供的一种将数据导出的功能。该功能可以将用户指定的表或分区的数据以文本的格式,通过Broker进程导出到远端存储上,如HDFS/BOS等。 1.1 基本原理 用户提交一个 Export 作业后。Doris 会统计这个作业涉及的所有 Tablet。然后对这些 Tablet 进行分…

自动驾驶学习笔记(十三)——感知基础

#Apollo开发者# 学习课程的传送门如下&#xff0c;当您也准备学习自动驾驶时&#xff0c;可以和我一同前往&#xff1a; 《自动驾驶新人之旅》免费课程—> 传送门 《Apollo Beta宣讲和线下沙龙》免费报名—>传送门 文章目录 前言 传感器 测距原理 坐标系 标定 同…

2023/12/3总结

RabbitMq 消息队列 下载地址RabbitMQ: easy to use, flexible messaging and streaming — RabbitMQ 使用详情RabbitMQ使用教程(超详细)-CSDN博客 实现延迟队列&#xff08;为了实现订单15分钟后修改状态&#xff09; 1 死信队列 当一个队列中的消息满足下列情况之一时&…

华为OD机试真题-找城市-2023年OD统一考试(C卷)

题目描述: 一张地图上有n个城市,城市和城市之间有且只有一条道路相连:要么直接相连,要么通过其它城市中转相连(可中转一次或多次)。城市与城市之间的道路都不会成环。 当切断通往某个城市 i 的所有道路后,地图上将分为多个连通的城市群,设该城市 i 的聚集度为 DPi(Deg…

【risc-v】易灵思efinix FPGA riscv 时钟配置的一些总结

系列文章目录 分享一些fpga内使用riscv软核的经验&#xff0c;共大家参考。后续内容比较多&#xff0c;会做成一个系列。 本系列会覆盖以下FPGA厂商 易灵思 efinix 赛灵思 xilinx 阿尔特拉 Altera 本文内容隶属于【易灵思efinix】系列。 文章目录 系列文章目录前言一、pan…

为何要3次握手?TCP协议的稳定性保障机制

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 仓库主页&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 欢迎点赞…

操作系统·存储器管理

根据冯诺依曼原理&#xff0c;程序必须先存储在内存中&#xff0c;才可以执行。 在多道程序并发执行的系统存储器管理非常重要。 5.1 存储器管理的功能 5.1.1 主存分配与回收 要完成内存的分配和回收工作&#xff0c;要求设计者选择和确定几种策略和结构&#xff1a; 1.调入…

STM32F407-14.3.10-01PWM模式

PWM 模式 脉冲宽度调制模式可以生成一个信号&#xff0c;该信号频率由 TIMx_ARR⑩ 寄存器值决定&#xff0c;其占空比由 TIMx_CCRx⑤ 寄存器值决定。 通过向 TIMx_CCMRx 寄存器中的 OCxM⑰ 位写入 110 &#xff08;PWM 模式 1&#xff09;或 111 &#xff08;PWM 模式 2&#…

已解决log4j:WARN No appenders could be found for logger(org.apache.ibatis.logging.LogFactory).异常的正确解决方法

已解决log4j:WARN No appenders could be found for logger(org.apache.ibatis.logging.LogFactory).异常的正确解决方法&#xff0c;亲测有效&#xff01;&#xff01;&#xff01; 文章目录 报错问题解决思路解决方法交流 报错问题 log4j:WARN No appenders could be found …

SpringCloud简介和用处

Spring Cloud是一套基于Spring Boot的微服务框架&#xff0c;它旨在提供一种快速构建分布式系统的方法。它可以帮助开发人员构建具有高可用性、可扩展性和容错性的微服务&#xff0c;并通过Spring Boot的开发工具和库提供强大的支持。 一、简介 Spring Cloud是Spring家族中的一…

React如何像Vue一样将css和js写在同一文件

如果想在React中想要像Vue一样把css和js写到一个文件中&#xff0c;可以使用CSS-in-JS。 使用CSS-in-JS 下载 npm i styled-components使用 就像写scss一样&#xff0c;不过需要声明元素的类型 基本语法及展示如下&#xff0c; import styled from "styled-component…

鸿蒙开发:Stage模型开发-应用/组件级配置以及UIAbility组件初步使用【鸿蒙专栏-20】

文章目录 Stage模型开发概述基本概念UIAbility组件和ExtensionAbility组件WindowStageContextAbilityStage开发流程应用组件开发了解进程模型了解线程模型应用配置文件应用版本声明配置Module支持的设备类型配置Module权限配置进阶应用配置

C语言实现Cohen_Sutherland算法

前提简要&#xff1a; 算法简介&#xff1a; 编码算法是最早、最流行的线段裁剪算法&#xff0c;该算法采用区域检验的方法&#xff0c;能够快速有效地判断一条线段与裁剪窗口的位置关系&#xff0c;对完全接受或完全舍弃的线段无需求交&#xff0c;即可直接识别。 算法思想&…

Python - 字典3

修改字典项 您可以通过引用其键名来更改特定项的值&#xff1a; 示例&#xff0c;将 “year” 更改为 2018&#xff1a; thisdict {"brand": "Ford","model": "Mustang","year": 1964 } thisdict["year"] 20…

GO基础之变量与常量

标识符与关键字 标识符 在编程语言中标识符就是程序员定义的具有特殊意义的词&#xff0c;比如变量名、常量名、函数名等等。 Go语言中标识符由字母数字和_(下划线&#xff09;组成&#xff0c;并且只能以字母和_开头。 举几个例子&#xff1a;abc, _, _123, a123。 关键字 关键…

周周清(1)

项目进度&#xff1a; 最近一直在搭建环境&#xff0c;都没写什么&#xff1a;登陆页面采用登陆注册在同一个界面&#xff0c;用v-if进行渲染&#xff0c;并且借助validation插件中的yup神器进行校验&#xff0c; <script setup> // import { ref } from vue import * …

Java流Stream使用详解(上)

Java流Stream使用详解 体验Stream流的作用 需求&#xff1a;按照下面的要求完成集合的创建和遍历创建一个集合&#xff0c;存储多个字符串元素 ArrayList<String> list new ArrayList<>(); list.add("张无忌"); list.add("周芷若"); lis…