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 ...
随机推荐
- .Net知识大全(个人整理)
.Net知识大全 本章内容适用于对.NET有一定基础的或者是想通过本文章对.NET基础知识记不清楚的朋友,可以通过本文章进行回顾. 面试的时候可能也会遇到相应的题目,建议面试前进行回顾!!! 1.NE ...
- 基于 MySQL Binlog 的 Elasticsearch 数据同步实践 原
一.背景 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品.订单等数据的多维度检索. 使用 Elasticsearch 存储业务数据可以 ...
- 有趣的PHP一句话
今天看到如下图所示的PHP一句话,觉得挺有意思. 代码如下: <?=~$_='$<>/'^'{{{{';echo $_;@${$_}[_](@${$_}[__]);?> 效果图 ...
- SpringBoot Jpa入门案例
版权声明:署名,允许他人基于本文进行创作,且必须基于与原先许可协议相同的许可协议分发本文 (Creative Commons) 我们先来了解一下是什么是springboot jpa,springboo ...
- Fedora dnf配置
1.在配置文件/etc/dnf/dnf.conf中加入: fastestmirror=true keepcache=true 这样下载安装软件就快多了. 2.dnf常用命令 检查并升级可用软件包: $ ...
- php if语句
一.前言 if语句 是几乎所有编程语言都有的函数. 当然我们最好的php这么最好的语言也有啦~ 二.搞起! 直接上代码不多哔哔.talk is cheap show me the code 2.1 i ...
- Cocos2d-x 3.x 学习笔记(6):Sprite SpriteFrameCache Texture2D TextureCache
1. 概述 TextureCache是对Texture2D纹理的缓存,SpriteFrameCache是对SpriteFrame的缓存,每个SpriteFrame是对Texture2D的封装,Spri ...
- [leetcode] #213 House Robber II Medium (medium)
原题链接 比子母题House Robber多了一个条件:偷了0以后,第n-1间房子不能偷. 转换思路为求偷盗[0,n-1)之间,以及[1,n)之间的最大值. 用两个DP,分别保存偷不偷第0间房的情况. ...
- 使用 Spring Framework 时常犯的十大错误
Spring 可以说是最流行的 Java 框架之一,也是一只需要驯服的强大野兽.虽然它的基本概念相当容易掌握,但成为一名强大的 Spring 开发者仍需要很多时间和努力. 在本文中,我们将介绍 Spr ...
- Flutter初体验--环境搭建
Fluter最近火了起来,它的有点很多,今天我做一篇在Windows下安装Flutter的教程. 一.下载 无论你要安装什么软件,都要先下载下来.我用的是SourceTree,地址: https ...