@Test
public void testPaceController_multiThread() throws InterruptedException {
final PaceController paceController = new PaceController(1000, 160d);
final Node node = mock(Node.class); final AtomicInteger passcount = new AtomicInteger();
final AtomicInteger blockcount = new AtomicInteger(); final AtomicInteger done = new AtomicInteger();
AtomicLong lastTm = new AtomicLong(System.currentTimeMillis() / 1000);
int count = 1000;
final CountDownLatch countDown = new CountDownLatch(count); for (int i = 0; i < count; i++) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
for(int j =0; j< 10; j++) {
boolean pass = paceController.canPass(node, 1).isPass(); if (pass == true) {
passcount.incrementAndGet();
} else {
blockcount.incrementAndGet();
}
done.incrementAndGet();
long now = System.currentTimeMillis() / 1000;
if (lastTm.get() != now) {
System.out.println("pass:" + passcount.get() + ", tm:" + lastTm.get());
System.out.println("block:" + blockcount.get() + ", tm:" + lastTm.get());
System.out.println("done:" + done.get() + ", tm:" + lastTm.get());
passcount.set(0);
blockcount.set(0);
done.set(0);
}
lastTm.set(now);
}
countDown.countDown();
}
}, "Thread " + i);
thread.start();
}
countDown.await();
System.out.println("pass:" + passcount.get() + ", tm:" + lastTm.get());
System.out.println("block:" + blockcount.get() + ", tm:" + lastTm.get());
System.out.println("done:" + done.get() + ", tm:" + lastTm.get()); }
1.CountDownLatch 同步并发处理
countDown.countDown 递减为0,等待发射信号。

countDown.await()阻塞当前线程,等待调用。
2.AtomicInteger 和 volatile 的区别,CAS原子性操作。

volatile关键字很重要的两个特性:

1、保证变量在线程间可见,对volatile变量所有的写操作都能立即反应到其他线程中,换句话说,volatile变量在各个线程中是一致的(得益于java内存模型—"先行发生原则");

2、禁止指令的重排序优化;

所以volatile 并非原子性操作。

AtomicInteger非阻塞同步(原子性CAS)

同步:多线程并发访问共享数据时,保证共享数据再同一时刻只被一个或一些线程使用。

我们知道,阻塞同步和非阻塞同步都是实现线程安全的两个保障手段,非阻塞同步对于阻塞同步而言主要解决了阻塞同步中线程阻塞和唤醒带来的性能问题,那什么叫做非阻塞同步呢?在并发环境下,某个线程对共享变量先进行操作,如果没有其他线程争用共享数据那操作就成功;如果存在数据的争用冲突,那就才去补偿措施,比如不断的重试机制,直到成功为止,因为这种乐观的并发策略不需要把线程挂起,也就把这种同步操作称为非阻塞同步(操作和冲突检测具备原子性)。在硬件指令集的发展驱动下,使得 "操作和冲突检测" 这种看起来需要多次操作的行为只需要一条处理器指令便可以完成,这些指令中就包括非常著名的CAS指令(Compare-And-Swap比较并交换)。《深入理解Java虚拟机第二版.周志明》第十三章中这样描述关于CAS机制:

图取自《深入理解Java虚拟机第二版.周志明》13.2.2
所以再返回来看AtomicInteger.incrementAndGet()方法,它的时间也比较简单

/**
* Atomically increments by one the current value.
*
* @return the updated value
*/
public final int incrementAndGet() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
  return next;
}
}

incrementAndGet()方法在一个无限循环体内,不断尝试将一个比当前值大1的新值赋给自己,如果失败则说明在执行"获取-设置"操作的时已经被其它线程修改过了,于是便再次进入循环下一次操作,直到成功为止。这个便是AtomicInteger原子性的"诀窍"了,继续进源码看它的compareAndSet方法:

/**
* Atomically sets the value to the given updated value
* if the current value {@code ==} the expected value.
*
* @param expect the expected value
* @param update the new value
* @return true if successful. False return indicates that
* the actual value was not equal to the expected value.
*/
public final boolean compareAndSet(int expect, int update) {
  return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}

可以看到,compareAndSet()调用的就是Unsafe.compareAndSwapInt()方法,即Unsafe类的CAS操作。

一段JAVA代码了解多线程,JUC、CAS原子性操作。的更多相关文章

  1. jsp页面:js方法里嵌套java代码(是操作数据库的),如果这个js 方法没被调用,当jsp页面被解析的时候,不管这个js方法有没有被调用这段java代码都会被执行?

    jsp页面:js方法里嵌套java代码(是操作数据库的),如果这个js 方法没被调用,当jsp页面被解析的时候,不管这个js方法有没有被调用这段java代码都会被执行? 因为在解析时最新解析的就是JA ...

  2. java 多线程12 : 无锁 实现CAS原子性操作----原子类

    由于java 多线程11:volatile关键字该文讲道可以使用不带锁的情况也就是无锁使变量变成可见,这里就理解下如何在无锁的情况对线程变量进行CAS原子性及可见性操作 我们知道,在并发的环境下,要实 ...

  3. 你觉得我的这段Java代码还有优化的空间吗?

    上周,因为要测试一个方法的在并发场景下的结果是不是符合预期,我写了一段单元测试的代码.写完之后截了个图发了一个朋友圈,很多人表示短短的几行代码,涉及到好几个知识点. 还有人给出了一些优化的建议.那么, ...

  4. linux学习之---在linux服务器上跑一段Java代码

    经常在windows上进行开发,有时候,需要在Linux环境上跑一些程序测下代码,要怎么办才好嘞? 假设你对Java常用命令和linux常用命令已经基本熟悉,就可以直接按照以下步骤来啦,默认linux ...

  5. 如何看一段JAVA代码耗了多少内存

    简单的方法,如下: Runtime r = Runtime.getRuntime();  r.gc();  long startMem = r.freememory(); // 开始时的剩余内存  你 ...

  6. 在jsp中默认写上的一段java代码表示basePath 的路径的具体的意思是什么?

    <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" ...

  7. [Java]简单计算下一段Java代码段运行了多少秒

    long startTime = System.currentTimeMillis(); ...... long endTime = System.currentTimeMillis(); logge ...

  8. JAVA多线程提高五:原子性操作类的应用

    当程序更新一个变量时,如果多线程同时更新这个变量,可能得到期望之外的值,比如变量i=1,A线程更新i+1,B线程也更新i+1,经过两个线程操作之后可能i不等于3,而是等于2.因为A和B线程在更新变量i ...

  9. JAVA多线程学习九-原子性操作类的应用

    当程序更新一个变量时,如果多线程同时更新这个变量,可能得到期望之外的值,比如变量i=1,A线程更新i+1,B线程也更新i+1,经过两个线程操作之后可能i不等于3,而是等于2.因为A和B线程在更新变量i ...

随机推荐

  1. message.go

    +MsgIDLength:]     return &msg, nil } func writeMessageToBackend(buf *bytes.Buffer, msg *Message ...

  2. BZOJ_2393_Cirno的完美算数教室&&BZOJ_1853_[Scoi2010]幸运数字 _深搜+容斥原理

    BZOJ_2393_Cirno的完美算数教室&&BZOJ_1853_[Scoi2010]幸运数字 _深搜+容斥原理 题意: ~Cirno发现了一种baka数,这种数呢~只含有2和⑨两种 ...

  3. Java IO--字符流--InputStreamReader 和 OutputStreamWriter

    今天继续学习字符流的子类!!!! 先来熟悉一下适配器设计模式:(手写的,,嘿嘿) 因为据说InputStreamReader 和OutputStreamWriter采用了适配器模式(现在我还没能理解, ...

  4. 微信jssdk config:invalid signature 签名错误 ,问题排查过程

    invalid signature签名错误.建议按如下顺序检查: 确认签名算法正确,可用 http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisi ...

  5. 读书笔记--Android Gradle权威指南(下)

    前言 最近看了一本书<Android Gradle 权威指南>,收获挺多,就想着来记录一些读书笔记,方便后续查阅. 本篇内容是基于上一篇:读书笔记--Android Gradle权威指南( ...

  6. koa+mysql+vue+socket.io全栈开发之web api篇

    目标是建立一个 web QQ的项目,使用的技术栈如下: 后端是基于koa2 的 web api 服务层,提供curd操作的http接口,登录验证使用的是 json web token,跨域方案使用的是 ...

  7. 通过user.MYD MySQL密码

    具体的获取方法: 1)通过hex 十六进制的工具打开user.MYD文件 这里使用:0XED 2)复制MySQL密码出来,进行分析 *CEAF6E9FA3A448A25AC9D00C8D7078385 ...

  8. React 项目生产版本迭代页面不刷新问题

    React 页面缓存 react 打包项目进行服务端部署后,会发现index.html被浏览器缓存,访问项目url指向的还是上个版本的内容.原理是index.html被缓存后,路由指向和跳转都是旧版的 ...

  9. JVM利器:Serviceability Agent介绍

    本文首发于公众号:javaadu 简单介绍 构建高性能的Java应用过程中,必然会遇到各种各样的问题,像CPU飙高.内存泄漏.应用奔溃,以及其他疑难杂症,这时可以使用Serviceability Ag ...

  10. Windows无人值守文件unattend制作以及自定义系统安装

    原文链接:Create media for automated unattended install of Windows 10 我从来没看到过像上面的文章一样这么详细的描述过Windows10的无人 ...