Java并发测试
要求:模拟200个设备,尽量瞬间并发量达到200。
思路
第一种:线程池模拟200个线程——wait等待线程数达200——notifyAll唤醒所有线程
第二种:线程池模拟200个线程——阻塞线程——达到200条件释放
比较
两种方案都可以实现瞬时高并发的模拟,但是建议使用第二种方案。
第一种方案中,压测过程中,wait状态下的线程已经释放对象上的锁定,唤醒时会极大的消耗CPU资源。压测程序可能直接导致机器崩溃
第二种方案,由于阻塞过程中,线程不会释放掉目前持有的对象资源,因此等待条件释放不会造成资源的过度消耗。
但是应当选择好阻塞方式,避免线程操作时的死锁。同时实现线程之间的通信。
wait-notifyAll
代码较简单,通过线程池启动1000个线程,通过synchronized保证线程可见性,和安全性。
当线程数量未达到1000时,wait使线程退出CPU,释放锁。
当线程数量达到1000时,notifyAll通知等待集上的线程,唤醒线程。
代码如下:
/**
* @author: irvingyuan
* @since 2017年1月22日 下午4:51:51
* @version:
*/
public class Parallellimit {
public static void main(String[] args) {
ExecutorService pool = Executors.newCachedThreadPool();
Counts count = new Counts(); //共享操作该计数变量,不能使用int或者integer,Java无法对非对象、和包装类进行加锁wait
count.num = 0;
for(int i=0;i<10000;i++){ //启动线程
MyRunnable runnable = new MyRunnable(count);
pool.execute(runnable);
}
pool.shutdown(); //关闭线程池,无法加入新线程任务,但不影响现有线程
}
}
public class MyRunnable implements Runnable{
private Counts count ;
/**
* 通过构造方法传入初值,避免set和get时线程的不安全性
*/
public MyRunnable(Counts count){
this.count = count;
}
public void run() {
try {
/**
* 加锁,保证线程可见性和安全性
*/
synchronized (count) {
count.num++;
if(count.num<10000){
System.out.println(count.num);
count.wait();//一定要调用count对象的wait,默认对this,无法持有线程的锁,抛出异常
}
/**
* 达到10000时唤醒所有线程
*/
if(count.num == 10000){
count.notifyAll();
}
System.out.println("并发量 count="+count.num);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
测试结果
并发唤醒1000个线程时,CPU瞬时使用率瞬时增长17%左右。可见CPU负担很大。
继续增大线程数,JVM抛OOM异常退出,需要修改启动参数
block阻塞方式
同步代码块持有count的锁,保证创建出正确的线程数量。判断不够并发量时,使用while阻塞线程。
当达到并发量时,阻塞条件失效,线程继续运行。
代码如下:
/**
* 阻塞方式创建瞬时高并发
* @author: irvingyuan
* @since 2017年1月23日 下午4:45:56
* @version:
*/
public class BlockRunnable implements Runnable{
private Counts count ;
/**
* 通过构造方法传入初值,避免set和get时线程的不安全性
*/
public BlockRunnable(Counts count){
this.count = count;
}
public void run() {
/**
* this肯定失效,this调用处为runnable对象
* 此时加锁表示多个线程只能有一个线程在某时刻操作该runnable
* new出来了n个线程,自己调用自己的,this必定失效
* synchronized (this) {
*/
synchronized (count) {
count.num++;
System.out.println("Thread count = "+count.num);
}
/**
* 注意synchronized的粒度
* while放在代码快中会导致线程一直持有锁等待,下一个线程无法生成和进行
*/
while(count.num<100);
//并发操作
System.out.println("concurrency count = "+count.num);
}
}
测试效果
100个线程瞬时的CPU使用率居然激增到了100%,和资料说的完全想法,更加损耗系统资源。(是不是因为while?)
//原文使用sleep,个人认为时间不好掌握,用while直接长时间做条件阻塞
CountDownLatch
Java提供的实现阻塞和释放线程的类,尝试是否符合推荐的规律。
其中主要包含三个方法
countDownLatch(100) 类通过构造方法传入计数数量。
countDown() 方法会减少一个计数值
await() 方法自动阻塞线程,直到count的值变为0
执行过程中,同步操作count后,开始等待,直到100个线程全部创建后并发执行
代码如下
public class Parallellimit {
public static void main(String[] args) {
ExecutorService pool = Executors.newCachedThreadPool();
Counts count = new Counts();
count.num = 0;
CountDownLatch cdl = new CountDownLatch(100);
for(int i=0;i<100;i++){
CountRunnable runnable = new CountRunnable(cdl);
pool.execute(runnable);
}
}
}
/**
* 〈countDownlatch实现高并发〉
* @author: irvingyuan
* @since 2017年1月23日 下午5:45:59
* @version:
*/
public class CountRunnable implements Runnable {
private CountDownLatch countDownLatch;
public CountRunnable(CountDownLatch countDownLatch){
this.countDownLatch = countDownLatch;
}
public void run() {
try {
/**
* 不加锁也可以支持,虽然打印出的值不对,但最后计算次数却是100次
* 说明确实是执行了整整100次才并发,计算次数正确
*/
synchronized (countDownLatch) {
/**
* 每次减少一个容量
*/
countDownLatch.countDown();
System.out.println("thread counts = "+(countDownLatch.getCount()));
}
/**
* 阻塞线程,直到countDown至0
*/
countDownLatch.await();
System.out.println("concurrency counts = "+(100-countDownLatch.getCount()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
测试结果
CPU增长率大约10%左右,相对于wait-notify方式要减少约一半。
综上,阻塞似乎是最坑爹的一种方式
Java并发测试的更多相关文章
- Java并发编程(三):并发模拟(工具和Java代码介绍)
并发模拟工具介绍 ① Postman : Http请求模拟工具 从图上我们可以看出,Postman模拟并发其实是分两步进行操作的.第一步:左边的窗口,在窗口中设置相关接口以及参数,点击运行进行第二步. ...
- Java接口多线程并发测试 (一)
本文为作者原创,禁止转载,违者必究法律责任!!! 本文为作者原创,禁止转载,违者必究法律责任!!! Java接口多线程并发测试 一,首先写一个接口post 请求代码: import org.apach ...
- java高并发测试代码
package com.example.test; import java.net.URL;import java.net.URLConnection;import java.util.concurr ...
- 《Java并发编程实战》第十二章 测试并发程序 读书笔记
并发测试分为两类:安全性测试(无论错误的行为不会发生)而活性测试(会发生). 安全測试 - 通常採用測试不变性条件的形式,即推断某个类的行为是否与其它规范保持一致. 活跃性測试 - 包含进展測试和无进 ...
- Java自动化测试框架-11 - TestNG之annotation与并发测试篇 (详细教程)
1.简介 TestNG中用到的annotation的快速预览及其属性. 2.TestNG基本注解(注释) 注解 描述 @BeforeSuite 注解的方法只运行一次,在当前suite所有测试执行之前执 ...
- Java高并发测试框架JCStress
前言 如果要研究高并发,一般会借助高并发工具来进行测试.JCStress(Java Concurrency Stress)它是OpenJDK中的一个高并发测试工具,它可以帮助我们研究在高并发场景下JV ...
- 白盒测试中如何实现真正意义上并发测试(Java)
在这个话题开始之前,首先我们来弄清楚为什么要做并发测试? 一般并发测试,是指模拟并发访问,测试多用户并发访问同一个应用.模块.数据时是否产生隐藏的并发问题,如内存泄漏.线程锁.资源争用问题. 站在性能 ...
- JAVA并发编程J.U.C学习总结
前言 学习了一段时间J.U.C,打算做个小结,个人感觉总结还是非常重要,要不然总感觉知识点零零散散的. 有错误也欢迎指正,大家共同进步: 另外,转载请注明链接,写篇文章不容易啊,http://www. ...
- 【Java并发系列01】Thread及ThreadGroup杂谈
img { border: solid black 1px } 一.前言 最近开始学习Java并发编程,把学习过程记录下.估计不是那么系统,主要应该是Java API的介绍(不涉及最基础的概念介绍), ...
随机推荐
- 使用python把html网页转成pdf文件
我们看到一些比较写的比较好文章或者博客的时候,想保存下来到本地当一个pdf文件,当做自己的知识储备,以后即使这个博客或者文章的连接不存在了,或者被删掉,咱们自己也还有. 当然咱们作为一个coder,这 ...
- Linux elasticsearch 安装 遇到的问题
备注:我的 Linux 测试机 是2G 内存的 ,估计内存小于 我的内存肯定会出这个问题 .(安装的最新版6.3.2) 1. 下载文件 解压 2 .试着 运行 bin 下面的 elasticse ...
- 联想服务器配置 RAID
联想服务器配置 RAID BIOS 中配置 RAID 阵列卡 x3650 和 x3850 一.进入 RAID 1.在开机自检时按 F1 进入 UEFI 配置界面 2.选择 System Setting ...
- C语言sscanf用法解析与正则表达式支持
最近学习算法和输入输出用到的基本知识,首先是我自己写的一份代码参考和学习了很多资源 后面会给出参考资料,他们写得更加详细,正则表达式的支持确实是一大亮点所在 #include<iostream& ...
- 更改默认打开wifi功能
一.打开以下目录 /home/tingpan/openwrt/barrier_breaker/package/kernel/mac80211/files/lib/wifi 找到mac80211.sh ...
- 专访TK教主于旸:原来那些搞安全的说的都是真的(图灵访谈)
引用:http://www.ituring.com.cn/article/196609 于旸,网名“tombkeeper”,在国内黑客界被尊称为“TK教主”,现任腾讯玄武实验室总监.于旸从事信息安全研 ...
- 织梦调用文章 ID (来源:百度知道)
问:{dede:field.id /} {dede:channel type='son' orderby='sortrank'} <a href='[field:typeurl/]'>&l ...
- 跨域获取json数据
原文地址:http://my.oschina.net/LinBandit/blog/34570 前阵子做了一个前端动态加载json数据的应用,其中使用xmlhttprequest动态加载js,但是 ...
- Linux下查看系统版本号信息的方法(转载)
原文出处 http://www.ha97.com/2987.html 1.cat /proc/version [root@localhost ~]# cat /proc/versionLinux v ...
- LayUI——数据表格使用
Layui数据表格的实际项目使用 Layui的数据表格可谓是在后台管理的页面中经常用到的工具了 最近做项目就用到了,项目的要求是用数据表格显示出后台文章的列表并且每一行的文章都有对应的修改删除操作按钮 ...