当前位置: 首页 > news >正文

亚网互联网站设计seo入门培训学多久

亚网互联网站设计,seo入门培训学多久,手机网站 案例,seo中文含义写在前面 本文一起来看下使用JUC包的AtomicXxxxFieldUpdater实现更新的原子性。代码位置如下: 当前有针对int,long,ref三种类型的支持。如果你需要其他类型的支持的话,也可以照葫芦画瓢。 1:例子 1.1:普…

写在前面

本文一起来看下使用JUC包的AtomicXxxxFieldUpdater实现更新的原子性。代码位置如下:
在这里插入图片描述
当前有针对int,long,ref三种类型的支持。如果你需要其他类型的支持的话,也可以照葫芦画瓢。

1:例子

1.1:普通方式

程序:

package x;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;public class NormalUpdaterTest {CountDownLatch countDownLatch = new CountDownLatch(1);public static void main(String[] args) throws InterruptedException {Account account = new Account(0);List<Thread> list = new ArrayList<>();for (int i = 0; i < 20; i++) {Thread t = new Thread(new Task(account));list.add(t);t.start();}for (Thread t : list) {t.join();}System.out.println(account.toString());}private static class Task implements Runnable {private Account account;Task(Account account) {this.account = account;}@Overridepublic void run() {for (int i = 0; i < 5; i++) {try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}account.increMoney();}}}static class Account {private volatile int money;public Account(int initial) {this.money = initial;}public void increMoney() {money++;}public int getMoney() {return money;}@Overridepublic String toString() {return "Account{" +"money=" + money +'}';}}
}

我们期望的结果是100,但结果往往是比100小的,因为整个操作过程并不是线程安全的,根本原因是这个i++它不是原子的,而是三步走,首先拿到i,接着对i+1,最后将i+1的结果写回内存,所以大概率存在盖结果情况发生,运行如下:

Account{money=91}Process finished with exit code 0

当然这个结果并不是固定不变,因为存在偶然性,但一般都是小于100的。

1.2:原子方式

package x;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;public class FieldlUpdaterTest {CountDownLatch countDownLatch = new CountDownLatch(1);public static void main(String[] args) throws InterruptedException {Account account = new Account(0);List<Thread> list = new ArrayList<>();for (int i = 0; i < 20; i++) {Thread t = new Thread(new Task(account));list.add(t);t.start();}for (Thread t : list) {t.join();}System.out.println(account.toString());}private static class Task implements Runnable {private Account account;Task(Account account) {this.account = account;}@Overridepublic void run() {for (int i = 0; i < 5; i++) {try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}account.increMoney();}}}static class Account {private volatile int money;private AtomicIntegerFieldUpdater fieldUpdater = AtomicIntegerFieldUpdater.newUpdater(Account.class, "money");public Account(int initial) {this.money = initial;}public void increMoney() {
//            money++;
//            fieldUpdater.incrementAndGet(money);// 以原子的方式更新this的moneyfieldUpdater.incrementAndGet(this);}public int getMoney() {return money;}@Overridepublic String toString() {return "Account{" +"money=" + money +'}';}}
}

相比于普通方式增加了AtomicIntegerFieldUpdater fieldUpdater专门用来负责更新,更新逻辑也对应的变为fieldUpdater.incrementAndGet(this);,这个时候再运行:

Account{money=100}Process finished with exit code 0

就对了,因为此时加了cas的乐观锁。

2:源码分析

首先看下代码AtomicIntegerFieldUpdater fieldUpdater = AtomicIntegerFieldUpdater.newUpdater(Account.class, "money");:

AtomicIntegerFieldUpdaterImpl(final Class<T> tclass,final String fieldName,final Class<?> caller) {final Field field;final int modifiers;try {...} catch (Exception ex) {throw new RuntimeException(ex);}...// 获取要更新的类和字段的内存偏移量this.cclass = (Modifier.isProtected(modifiers) &&tclass.isAssignableFrom(caller) &&!isSamePackage(tclass, caller))? caller : tclass;this.tclass = tclass;this.offset = U.objectFieldOffset(field);
}

代码fieldUpdater.incrementAndGet(this);:

// java.util.concurrent.atomic.AtomicIntegerFieldUpdater.AtomicIntegerFieldUpdaterImpl#getAndAdd
public final int getAndAdd(T obj, int delta) {accessCheck(obj);// 基于偏移量完成更新,其中getAndAddInt是cas的return U.getAndAddInt(obj, offset, delta);
}// sun.misc.Unsafe#getAndAddIntsun.misc.Unsafe#getAndAddInt
public final int getAndAddInt(Object var1, long var2, int var4) {int var5;do {var5 = this.getIntVolatile(var1, var2);} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));return var5;
}

注意代码} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));当compare不成功的时候就会返回false,会尝试再次做+1操作,即自旋,直到成功。

3:相比于AtomicXxx的优势

更小的内存占用,为什么呢?比如如下代码:

class Account {private volatile int money;
}

如果改造为AtomicInteger的方式则为;

class Account {private volatile AtomicInteger money = new AtomicInteger(0);
}

AtomicInteger money的大小在不考虑padding的情况下大概为16字节对象头+4字节的对象内容,即20个字节,那么创建100个对象大小就是2000个字节,但如果是使用AtomicXxxFieldUpdater的代码就如下:

    private volatile int money;private static AtomicIntegerFieldUpdater fieldUpdater = AtomicIntegerFieldUpdater.newUpdater(Account.class, "money");
}

这里我们简单的假定AtomicIntegerFieldUpdater fieldUpdater的大小是24个字节,int money的大小是4个字节。此时我们创建100个对象,money和fieldUpdater占用的大小就是4*100+24,即424,因为fieldUpdater是静态的,所以只有独一份。
可以看到AtomicIntegerFieldUpdater的方式占用了比AtomicInteger少得多的内存,而占用更少的内存,也意味着你的程序不需要申请更多的内存,所以程序执行的速度也会更快。

写在后面

参考文章列表

jvm之对象大小分析。

多线程之JUC 。

http://www.mnyf.cn/news/33050.html

相关文章:

  • wordpress中文团队关键词优化排名
  • 西安网站工作室别做网络推广员
  • 哪里有做桥梁模型的网站百度教育会员
  • 0基础做网站杭州百度百家号seo优化排名
  • 网站推广意识薄弱上海百度seo牛巨微
  • 设计师做私单网站微信5000人接推广费用
  • 刚做的网站适合做外链吗win7一键优化工具
  • 建简单网站百度一下图片识别
  • JAVA网站301重定向怎么做推广普通话ppt课件
  • 怎么做网站多少钱网站建设排名优化
  • 玉溪建设局门户网站营销型网站建设托管
  • 网站推广怎么优化seo优化技术厂家
  • 邯郸怎样做网站今日头条关键词排名优化
  • wordpress knowhow 汉化广州优化防控措施
  • wordpress怎么找模板温州seo
  • go和java做网站郑州网络营销公司有哪些
  • 变更备案网站可以访问吗西安网站维护公司
  • 建设工程项目管理重庆seo网络营销
  • 免费门户网站模板下载win10系统优化工具
  • 如和做视频解析网站关键词排名点击软件网站
  • 刚做的网站关键字能搜到么百度指数人群画像怎么看
  • 公司建设网站的 计划书竞价推广怎么做
  • 做游戏门户网站要注意什么百度人工智能
  • 模板网站购买seo自动优化软件下载
  • 网站建设题目以及答案一键优化清理手机
  • 个人网站建设咨询电话运营和营销的区别和联系
  • 新的电商平台有哪些百度seo推广怎么做
  • wordpress国外全能主题推荐站长之家seo
  • 响应式网站建设公司淮北网站建设
  • 同江佳木斯网站设计南京百度seo公司