java并发编程(十四)----(JUC原子类)对象的属性修改类型介绍
今天我们介绍原子类的最后一个类型—-对象的属性修改类型: AtomicIntegerFieldUpdater,AtomicLongFieldUpdater,AtomicReferenceFieldUpdater。有了这几个方法,普通的变量也能享受原子操作了。
1. 开胃菜
由API我们知道AtomicIntegerFieldUpdater,AtomicLongFieldUpdater,AtomicReferenceFieldUpdater通过反射原子更新对象的字段,既然他们的作用是更新字段我们知道有些类型的字段是不可被更新的,所以被更新的字段是有一定的要求:
1. 必须是volatile类型(volatile是线程可见变量,保存在Jvm的主内存中,而不是线程的工作内存里面),
2. 字段的描述类型(修饰符public/protected/default/private)是调用者与操作对象字段的关系一致,
3. 只能是实例变量,不能是类变量,也就是说不能加static关键字,
4. 只能是可修改变量,不能使final变量,因为final的语义就是不可修改。实际上final的语义和volatile是有冲突的,这两个关键字不能同时存在,
5. 对于AtomicIntegerFieldUpdater和AtomicLongFieldUpdater只能修改int/long类型的字段,不能修改其包装类型(Integer/Long)。如果要修改包装类型就需要使用AtomicReferenceFieldUpdater。
2. 使用它
上面我们说了这几个类的作用是让普通类型的字段也能享受到原子操作,假如原本有一个变量是int型,并且很多地方都应用了这个变量,但是在某个场景下,想让int型变成AtomicInteger,但是如果直接改类型,就要改其他地方的应用。AtomicIntegerFieldUpdater就是为了解决这样的问题产生的。
AtomicIntegerFieldUpdater,AtomicLongFieldUpdater分别是对int和long类型的字段操作,AtomicReferenceFieldUpdater是对引用型的对象操作,并且在API中他们的操作方法与普通的AtomicInteger差不多,所以方法我就不再罗列,我们就直接使用吧。
我们来看AtomicIntegerFieldUpdater的例子:
/**
* allscore 如果和 score 的结果相同则说明线程是安全的
*/
public class AtomicIntegerFieldUpdaterTest {
public final static AtomicIntegerFieldUpdater<AA> vv = AtomicIntegerFieldUpdater.newUpdater(AA.class, "score"); //newUpdater方法为AA类中的score 对象创造一个更新器
public static AtomicInteger allscore = new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException
{
final AA stu = new AA();
Thread[] t = new Thread[10000];
for (int i = 0; i < 10000; i++)
{
t[i] = new Thread() {
@Override
public void run()
{
if(Math.random()>0.4)
{
vv.incrementAndGet(stu);
allscore.incrementAndGet();
}
}
};
t[i].start();
}
for (int i = 0; i < 10000; i++)
{
t[i].join();
}
System.out.println("score="+stu.getScore());
System.out.println("allscore="+allscore);
}
}
class AA{
int id;
volatile int score;
public int getScore()
{
return score;
}
public void setScore(int score)
{
this.score = score;
}
}
输出结果:
score=6032
allscore=6032
AtomicIntegerFieldUpdater包装过的int类型的score与 AtomicInteger 的allscore输出的值是一样的,足以见他们所起到的作用是一样。
我们说了AtomicIntegerFieldUpdater,那么AtomicLongFieldUpdater与它的用法大同小异,就不再说明。我们说这几个类是基于反射的实用工具,那么到底是怎么个反射法呢,我们不妨看看源码体验一下,上面用到了AtomicIntegerFieldUpdater.newUpdater()方法来指定类中的字段,我们不妨看看这个newUpdater是怎么执行的:
newUpdater()方法:
@CallerSensitive
public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
return new AtomicIntegerFieldUpdaterImpl<U>(tclass, fieldName, Reflection.getCallerClass());
}
我们看到在newUpdater方法上有一个注解:@CallerSensitive,关于这个注解我们可以探究一天的,暂时先埋一个伏笔哈,我们直接跟进去AtomicIntegerFieldUpdaterImpl方法:
AtomicIntegerFieldUpdaterImpl(Class<T> tclass, String fieldName, Class<?> caller) {
Field field = null;
int modifiers = 0;
try {
field = tclass.getDeclaredField(fieldName);
modifiers = field.getModifiers();
sun.reflect.misc.ReflectUtil.ensureMemberAccess(
caller, tclass, null, modifiers);
sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
Class fieldt = field.getType();
if (fieldt != int.class)
throw new IllegalArgumentException("Must be integer type");
if (!Modifier.isVolatile(modifiers))
throw new IllegalArgumentException("Must be volatile type");
this.cclass = (Modifier.isProtected(modifiers) &&
caller != tclass) ? caller : null;
this.tclass = tclass;
offset = unsafe.objectFieldOffset(field);
}
我们能看到该类里面都是我们常见到的反射的机制,除了sun.reflect.misc.ReflectUtil这个包里面的我们没用到以外。
我们再看一下AtomicReferenceFieldUpdater的使用:
public class AtomicReferenceFieldUpdaterTest {
public static void main(String[] args) {
TestAA testAA = new TestAA("xiaoming","nv",12);
AtomicReferenceFieldUpdater Updater = AtomicReferenceFieldUpdater.newUpdater(TestAA.class,String.class,"name");
Updater.compareAndSet(testAA,testAA.name,"liming");
System.out.println(testAA.getName());
}
}
class TestAA{
volatile String name;
volatile String sex;
volatile int age;
public TestAA(String name, String sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
输出为:
liming
Process finished with exit code 0
java并发编程(十四)----(JUC原子类)对象的属性修改类型介绍的更多相关文章
- java并发编程(十)----JUC原子类介绍
今天我们来看一下JUC包中的原子类,所谓原子操作是指不会被线程调度机制打断的操作:这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程),原子操作可以是 ...
- [Java并发编程(四)] Java volatile 的理论实践
[Java并发编程(四)] Java volatile 的理论实践 摘要 Java 语言中的 volatile 变量可以被看作是一种 "程度较轻的 synchronized":与 ...
- java多线程系类:JUC原子类:01之框架
本系列内容全部来自于http://www.cnblogs.com/skywang12345/p/3514589.html 特在此说明!!!!! 根据修改的数据类型,可以将JUC包中的原子操作类可以分为 ...
- java并发编程工具类JUC第四篇:LinkedBlockingQueue链表队列
在之前的文章中已经为大家介绍了java并发编程的工具:BlockingQueue接口.ArrayBlockingQueue.DelayQueue. LinkedBlockingQueue 队列是Blo ...
- java多线程系类:JUC原子类:03之AtomicLongArray原子类
概要 AtomicIntegerArray, AtomicLongArray, AtomicReferenceArray这3个数组类型的原子类的原理和用法相似.本章以AtomicLongArray对数 ...
- java并发编程工具类JUC第七篇:BlockingDeque双端阻塞队列
在之前的文章中已经为大家介绍了java并发编程的工具:BlockingQueue接口.ArrayBlockingQueue.DelayQueue.LinkedBlockingQueue.Priorit ...
- java并发编程工具类JUC第八篇:ConcurrentHashMap
在之前的文章中已经为大家介绍了java并发编程的工具:BlockingQueue接口.ArrayBlockingQueue.DelayQueue.LinkedBlockingQueue.Priorit ...
- 《Java并发编程实战》第三章 对象的共享 读书笔记
一.可见性 什么是可见性? Java线程安全须要防止某个线程正在使用对象状态而还有一个线程在同一时候改动该状态,并且须要确保当一个线程改动了对象的状态后,其它线程能够看到发生的状态变化. 后者就是可见 ...
- java并发编程(四) 线程池 & 任务执行、终止源码分析
参考文档 线程池任务执行全过程:https://blog.csdn.net/wojiaolinaaa/article/details/51345789 线程池中断:https://www.cnblog ...
随机推荐
- archery 平台升级部署实践
v1.3.8 → v1.5.0 1.安装.升级python3 venv 环境 1.1.安装 python36 全新安装需要执行,升级安装可忽略 https://www.cnblogs.com/Davi ...
- VMware下的Centos7实践Kvm虚拟化(通俗易懂)
虽然网上已经有很多关于kvm安装的教程了,但我还是看得头晕,有的教程里安装的包很多,有的很少,也没说明那些安装包的作用是干嘛的,用的命令也不一样,也没解释命令的意思是什么. 我重新写一个教程,尽量通俗 ...
- JsonUtil(基于Jackson的实现)
JsonUtil(基于Jackson的实现) 前言: 其实,我一直想写一个有关Util的系列. 其中有四个原因: Util包作为项目的重要组成,是几乎每个项目不可或缺的一部分.并且Util包的Util ...
- PG利用Multicorn访问CSV外部数据源
Multicorn 是一个 PostgreSQL 9.1+ 的扩展模块,用于简化外部数据封装开发,允许开发者使用 Python 编程语言开发. Install Multicorn Requiremen ...
- 从7点到9点写的小程序(用了模块导入,python终端颜色显示,用了点局部和全局可变和不可变作用域,模块全是自定义)
未完待续的小程序 要是能做的好看为啥不做的好看 在同目录下生成程序 1.程序文件 run.py from login import login from register import registe ...
- android异常 More than one file was found with OS independent path 'META-INF/XXX'
android 异常总结:一个文件在jar包中出现多次. Error:Execution failed for task ':app:transformResourcesWithMergeJavaRe ...
- Javascript中style,currentStyle和getComputedStyle的区别以及获取css操作方法
style: 只能获取行内style. 调用:obj.style.属性; 兼容:都兼容 currentStyle: 可以获取该obj所有style,但只可读. 调用:obj.currentStyle[ ...
- fjnuoj 1003 学长的QQ号
题目: //QQ是一个9位数,由1,2,3,4,5,9组成,且第1.6位数字相同,第2.4位数字相同,第5.7位数字相同. //我的QQ就在符合上诉条件中的所有9位数从小到大排第 ...
- 《VR入门系列教程》之21---使用Unity开发GearVR应用
使用Unity开发GearVR应用 上一章我们介绍了如何运用Unity3D开发Oculus Rift应用,当然,这个便宜且强大的游戏引擎也可以用于GearVR的应用开发,这时我们需要用到Ocu ...
- 写这篇博客之前,我又忘了“==”和equals的区别。
没错.嘟嘟又把==号和equals 的区别给忘掉了 ==号比较基本类型的时候比的是值,比较引用类型的时候比较的是地址.equals比较基本类型的时候.... 脑子里关于这道题的答案好模糊好没有安全感 ...