AtomicIntegerArray和AtomicIntegerFieldUpdater

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

AtomicIntegerArray

对int数组中元素的操作不是原子性的,所以存在并发操作时,我们应该使用AtomicIntegerArray类来代替int数组。
下面是验证演示代码:

public class AtomicIntegerArrayDemo {static AtomicIntegerArray aiArr = new AtomicIntegerArray(5);static int[] intArr = new int[5];/*** 并发测试,对数组的每个元素进行递增操作*/public static void main(String[] args) throws InterruptedException {ExecutorService threadPool = Executors.newCachedThreadPool();for(int t = 0; t < 5; t++) {threadPool.execute(() -> {for (int i = 0; i < 1000000; i++) {aiArr.getAndIncrement(i % 5);}});threadPool.execute(() -> {for (int i = 0; i < 1000000; i++) {intArr[i % 5]++;}});}threadPool.shutdown();boolean b = threadPool.awaitTermination(5, TimeUnit.SECONDS);if(b) {System.out.println("aiArr:" + aiArr.toString());System.out.println("intArr:" + Arrays.toString(intArr));}else{System.out.println("time out.");}}
}

运行结果:

D:\Java\jdk1.8.0_171\bin\java.exe "-javaagent:D:\JetBrains\IntelliJ IDEA
aiArr:[1000000, 1000000, 1000000, 1000000, 1000000]
intArr:[892703, 891096, 892369, 892372, 893754]

AtomicIntegerArray的常用方法:

//获取数组长度
int length()//获取数组中下标为i的元素的值
int get(int i)//设置数组中下标为i的元素的值为newValue
void set(int i, int newValue)//设置数组中下标为i的元素的值为newValue,返回以前的值
int getAndSet(int i, int newValue)//如果数组中下标为i的元素的值等于入参expect,则把值修改为update,并返回ture,如果不等则不修改并返回false
boolean compareAndSet(int i, int expect, int update)// arr[i]++
int getAndIncrement(int i)// arr[i]--
int getAndDecrement(int i)// ++arr[i]
int incrementAndGet(int i)// --arr[i]int decrementAndGet(int i)//数组中下标为i的元素的值加上delta,返回以前的值
int getAndAdd(int i, int delta)//数组中下标为i的元素的值加上delta,返回新的值
int addAndGet(int i, int delta)//1.8新增方法,更新当前值,返回以前的值
int getAndUpdate(int i, IntUnaryOperator updateFunction)// 1.8新增方法,更新当前值,返回更新后的值
int updateAndGet(int i, IntUnaryOperator updateFunction)// 1.8新增方法,更新当前值,返回以前的值
int getAndAccumulate(int i, int x, IntBinaryOperator accumulatorFunction)// 1.8新增方法,更新当前值,返回更新后的值
int accumulateAndGet(int i, int x, IntBinaryOperator accumulatorFunction)
*** 1.8新增方法演示*/
@Test
public void atomicIntegerArrayMethodTest(){AtomicIntegerArray arr = new AtomicIntegerArray(2);arr.set(0, 10);//lambda表达式中参数operand表示数组下标为0的元素当前值int i1 = arr.getAndUpdate(0, operand -> operand / 2);System.out.println(i1); // result: 10System.out.println(arr.get(0)); // result: 5int i2 = arr.updateAndGet(0, operand -> operand * 3);System.out.println(i2); // result: 15System.out.println(arr.get(0)); // result: 15//lambda表达式中参数left表示数组下标为0的元素当前值,right表示第二个参数2int i3 = arr.getAndAccumulate(0, 2, (left, right) -> left * right);System.out.println(i3); // result: 15System.out.println(arr.get(0)); // result: 30int i4 = arr.accumulateAndGet(0, 2, (left, right) -> left * right);System.out.println(i4); // result: 60System.out.println(arr.get(0)); // result: 60
}

AtomicIntegerFieldUpdater

AtomicIntegerFieldUpdater是用来原子的操作对象中int类型字段的。 下面是验证演示代码:

public class AtomicIntegerFieldUpdaterDemo {/*** 并发测试,对Counter的index字段进行递增操作*/public static void main(String[] args) throws InterruptedException {Counter counter1 = new Counter();AtomicIntegerFieldUpdater<Counter> counterIndexFieldUpdater = AtomicIntegerFieldUpdater.newUpdater(Counter.class, "index");Counter counter2 = new Counter();ExecutorService threadPool = Executors.newCachedThreadPool();for(int t = 0; t < 5; t++) {threadPool.execute(() -> {for (int i = 0; i < 1000000; i++) {counter1.index++;}});threadPool.execute(() -> {for (int i = 0; i < 1000000; i++) {counterIndexFieldUpdater.getAndIncrement(counter2);}});}threadPool.shutdown();boolean b = threadPool.awaitTermination(5, TimeUnit.SECONDS);if(b) {System.out.println("counter1.index:" + counter1.index);System.out.println("counter2.index:" + counterIndexFieldUpdater.getAndIncrement(counter2));}else{System.out.println("time out.");}}
}class Counter{/** 必须是volatile修饰的 */public volatile int index = 0;
}

运行结果:

D:\Java\jdk1.8.0_171\bin\java.exe "-javaagent:D:\JetBrains\IntelliJ IDEA 
counter1.index:4192522
counter2.index:5000000

值得注意的是,使用的时候注意如下几点:

  1. 字段必须是volatile类型的,在线程之间共享变量时保证立即可见
  2. 字段的描述类型(修饰符public/protected/default/private)是与调用者与操作对象字段的关系一致。也就是说调用者能够直接操作对象字段,那么就可以反射进行原子操作。
  3. 对于父类的字段,子类是不能直接操作的,尽管子类可以访问父类的字段。
  4. 只能是实例变量,不能是类变量,也就是说不能加static关键字。
  5. 只能是可修改变量,不能使final变量,因为final的语义就是不可修改。
  6. 对于AtomicIntegerFieldUpdater和AtomicLongFieldUpdater只能修改int/long类型的字段,不能修改其包装类型(Integer/Long)。如果要修改包装类型就需要使用AtomicReferenceFieldUpdater。
    参考:Java并发学习(九)-AtomicIntegerFieldUpdater字段原子更新类

AtomicIntegerArray的常用方法:

//创建AtomicIntegerFieldUpdater对象,tclass为需要操作对象的类型,fieldName为需要操作字段名称
static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName)//如果obj中指定字段的值等于expect,则把该字段的值设为update
boolean compareAndSet(T obj, int expect, int update) //把obj中指定字段的值设置为newValue
void set(T obj, int newValue);//返回obj中指定字段的值
int get(T obj);//把obj中指定字段的值设置为newValue,返回以前的值
int getAndSet(T obj, int newValue)//i++
int getAndIncrement(T obj)//++i
int incrementAndGet(T obj)//i--
int getAndDecrement(T obj)
//--i
decrementAndGet(T obj)//把obj中指定字段的值加上delta,返回以前的值
int getAndAdd(T obj, int delta)//把obj中指定字段的值加上delta,返回更新后的值
int addAndGet(T obj, int delta)//1.8新增方法,更obj中指定字段的值,返回以前的值
int getAndUpdate(T obj, IntUnaryOperator updateFunction)//1.8新增方法,更obj中指定字段的值,返回更新后的值
int updateAndGet(T obj, IntUnaryOperator updateFunction)//1.8新增方法,更obj中指定字段的值,返回以前的值
int getAndAccumulate(T obj, int x, IntBinaryOperator accumulatorFunction)//1.8新增方法,更obj中指定字段的值,返回更新后的值
int accumulateAndGet(T obj, int x, IntBinaryOperator accumulatorFunction)

转载于:https://my.oschina.net/u/2424727/blog/1933993

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

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

相关文章

CMOS图像传感器——高动态范围

动态范围是CMOS 图像传感器中很重要的一项评价指标。动态范围指示了CMOS 图像传感器能够在同一帧图像中同时探测到的最大光强信号和最小光强信号的范围。动态范围通常用dB 形式来表示,其计算公式如下 其中Pmax 和Pmin 分别是最大非饱和光强与最小可探测光强。对于线性…

键盘绑定

1.理论: 从击键到内核,前后的执行情况,之间没有必然关联 按键->csrss.exe->win32!RawInputThread->win32k!OpenDevice->ZwCreateFile->NtCreateFile->ntIopParseDevice->nt!IoGetAttachedDevice ->IoAllocateIrp->nt!ObCreateObject->nt!IopfCal…

《Linux内核设计与实现》读书笔记(七)- 中断处理

中断处理一般不是纯软件来实现的&#xff0c;需要硬件的支持。通过对中断的学习有助于更深入的了解系统的一些底层原理&#xff0c;特别是驱动程序的开发。 主要内容&#xff1a; 什么是中断中断类型中断相关函数中断处理机制中断控制方法总结1. 什么是中断 为了提高CPU和外围硬…

入门视频采集与处理(学会分析YUV数据)

标签&#xff1a;分析码流 视频采集 RGB YUV 原创作品&#xff0c;允许转载&#xff0c;转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://ticktick.blog.51cto.com/823160/555791做视频采集与处理&#xff0c;自然少不了要学会分析…

数字后端——时序验证

时序验证则是采用时序分析等方法验证设计是否满足时序收敛&#xff0c;这些时序检验工作包括反向标定(back-annotation)、时序与功耗的检验、时序与信号完整性的检验和当代低功耗纳米先进设计中的“多模式多端角”(MMMC&#xff0c;multi-mode multi-comer)检验。 一、反向标定…

Hadoop系列(三)MapReduce Job的几种提交运行模式

Job执行可以分为本地执行或者集群执行。hadoop集群安装部署在远程centos系统中。使用经典的WordCount代码为例。 1. 本地执行模式&#xff08;本地为MacOS环境&#xff09;&#xff0c;无需启动远程的hadoop集群&#xff0c;本地job会提交给本地执行器LocalJobRunner去执行。 1…

2600: [Ioi2011]ricehubh

Description 乡间有一条笔直而长的路称为“米道”。沿着这条米道上 R 块稻田&#xff0c;每块稻田的坐标均为一个 1 到 L 之间(含 1 和 L)的整数。这些稻田按照坐标以不减的顺序给出&#xff0c;即对于 0 ≤ i <R&#xff0c;稻田 i 的坐标 X[i]满足 1 ≤ X[0] ≤ ... ≤ X[…

常见视频接口介绍,VGA,YPbPr,DVI,HDMI,DisplayPort

1&#xff0c;VGA(D-SUB) 这种是显示器最常见的&#xff0c;用了很多年&#xff0c;色域空间是RGB&#xff0c;也就是红绿蓝&#xff0c;模拟信号&#xff0c;无音频 插头是15针的&#xff0c;实际所需的最小针数应该是5针&#xff0c;也就是RGB三色信号&#xff0c;水平…

js 对已知数组数据的导出EXCEL

1. 方法一 <a id"frontExportLogLink" href"javascript:void(0)" ng-click"exportLog()" class"btn btn-danger">导出<span class"glyphicon glyphicon-question-sign mgl10" tooltip"{{不支持ie | translate…

芯片面积估计方法

一、概念 芯片面积的主要涵盖部分分为三部分 IO&#xff1a;芯片的信号及电源pad等Standard cell : 实现芯片的功能逻辑Macro block &#xff1a;第三方IP( PLL DAC POR Memory .etc )芯片面积估计就是通过目标工艺的库信息&#xff0c;设计的spec、以往设计的信息及&#xff…

WordPress开发之WP Custom Register Login插件试用

简介 WP Custom Register Login可以为你的WordPress网站前台增加注册、登录、找回密码的功能&#xff1b;你可以通过简码在任何页面上调用。此外&#xff0c;该插件还支持设置自动通过用户的电子邮件验证新帐户激活&#xff0c;自带算术验证码&#xff0c;有效防护垃圾注册。对…

Java数据类型(基本数据类型)学习

Java数据类型&#xff08;基本数据类型&#xff09;学习 与其他语言一样&#xff0c;Java编程同样存在&#xff0c;比如int a&#xff0c;float b等。在学习变量之前我就必须先了解Java的数据类型啦。 Java的数据类型包括基本数据类型和引用数据类型。具体如下&#xff1a; 各数…

电视信号——行场同步

电视信号分NTSC制和PAL制两种制式, NTSC制每秒刷新60次,而PAL制每秒刷新50次。 水平消隐&#xff1a;电子枪从左到右画出象素&#xff0c;它每次只能画一条扫描线&#xff0c;画下一条之前要先回到左边并做好画下一条扫描线的准备&#xff0c;这之间有一段时间叫做水平消隐&…

SLVS-EC接口学习

SLVS summarize 一、概述 SLVS-EC高速串行接口技术&#xff0c;在CIS和DSP&#xff08;数字信号处理器&#xff09;之间实现了高帧率的宽带像素数据传输。 SLVS-EC引入了一个优化的数据包格式和控制协议&#xff0c;几乎没有冗余&#xff0c;而且结构简单&#xff0c;仅由两层…

关于Unity中NGUI的Pivot和锚点

Pivot 1.创建一个Sprite类型的Sprite1节点&#xff0c;关联一个图集和一张贴图&#xff0c;用图中的六个按钮调整这个贴图的Pivot点&#xff0c;一共有八个点可以选择 2.再创建一个Sprite类型的Sprite2节点&#xff0c;作为Sprite1节点的子节点&#xff0c;关联一个图集和一张贴…

PrimeTime指南——概述和基本流程

PrimeTime&#xff08;PT&#xff09;是Synopsys的sign-off quality的静态时序分析工具。PrimeTime可以集成于逻辑综合和物理综合的流程&#xff0c;让设计者分析并解决复杂的时序问题&#xff0c;并提高时序收敛的速度。 一、概述 PT最大的两个特点是&#xff1a; 基于时序路…

yuv和yCbCr的差异

yuv和yCbCr的差异 一、和rgb之间换算公式的差异 yuv<-->rgb Y 0.299*R 0.587*G 0.114*B U -0.147*R - 0.289*G 0.436*B 0.492*(B- Y) V 0.615*R - 0.515*G - 0.100*B 0.877*(R- Y) R Y 1.140*V G Y - 0.394*U - 0.581*V B Y 2.032*U yCbCr<-->rgb Y’ 0…

配置zentaophp

原理&#xff1a; 首先&#xff0c;我们要明白为什么访问localhost就可以访问到我们的apache主页。 解析域名的时候&#xff0c;首先是从本地的hosts文件开始的。 如果查不到&#xff0c;才会去DNS服务器查询。 如果你在这里面写一行&#xff1a;127.0.0.1 www.baidu.com 百…

Android开发——RecyclerView特性以及基本使用方法(二)

0. 前言随着Android的发展&#xff0c;虽然ListView依旧重要&#xff0c;但RecyclerView确实越来越多的被大家使用。但显然并不能说RecyclerView就一定优于ListView&#xff0c;而是应该根据不同的需求选择最合适的进行使用。本篇将介绍我们为什么要使用RecyclerView&#xff…

pycharm中使用scrapy命命

2019独角兽企业重金招聘Python工程师标准>>> 这篇博客写的不错&#xff0c;亲测 https://blog.csdn.net/MAOZEXIJR/article/details/80678133 转载于:https://my.oschina.net/u/2511906/blog/1934993