要求:模拟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并发测试的更多相关文章

  1. Java并发编程(三):并发模拟(工具和Java代码介绍)

    并发模拟工具介绍 ① Postman : Http请求模拟工具 从图上我们可以看出,Postman模拟并发其实是分两步进行操作的.第一步:左边的窗口,在窗口中设置相关接口以及参数,点击运行进行第二步. ...

  2. Java接口多线程并发测试 (一)

    本文为作者原创,禁止转载,违者必究法律责任!!! 本文为作者原创,禁止转载,违者必究法律责任!!! Java接口多线程并发测试 一,首先写一个接口post 请求代码: import org.apach ...

  3. java高并发测试代码

    package com.example.test; import java.net.URL;import java.net.URLConnection;import java.util.concurr ...

  4. 《Java并发编程实战》第十二章 测试并发程序 读书笔记

    并发测试分为两类:安全性测试(无论错误的行为不会发生)而活性测试(会发生). 安全測试 - 通常採用測试不变性条件的形式,即推断某个类的行为是否与其它规范保持一致. 活跃性測试 - 包含进展測试和无进 ...

  5. Java自动化测试框架-11 - TestNG之annotation与并发测试篇 (详细教程)

    1.简介 TestNG中用到的annotation的快速预览及其属性. 2.TestNG基本注解(注释) 注解 描述 @BeforeSuite 注解的方法只运行一次,在当前suite所有测试执行之前执 ...

  6. Java高并发测试框架JCStress

    前言 如果要研究高并发,一般会借助高并发工具来进行测试.JCStress(Java Concurrency Stress)它是OpenJDK中的一个高并发测试工具,它可以帮助我们研究在高并发场景下JV ...

  7. 白盒测试中如何实现真正意义上并发测试(Java)

    在这个话题开始之前,首先我们来弄清楚为什么要做并发测试? 一般并发测试,是指模拟并发访问,测试多用户并发访问同一个应用.模块.数据时是否产生隐藏的并发问题,如内存泄漏.线程锁.资源争用问题. 站在性能 ...

  8. JAVA并发编程J.U.C学习总结

    前言 学习了一段时间J.U.C,打算做个小结,个人感觉总结还是非常重要,要不然总感觉知识点零零散散的. 有错误也欢迎指正,大家共同进步: 另外,转载请注明链接,写篇文章不容易啊,http://www. ...

  9. 【Java并发系列01】Thread及ThreadGroup杂谈

    img { border: solid black 1px } 一.前言 最近开始学习Java并发编程,把学习过程记录下.估计不是那么系统,主要应该是Java API的介绍(不涉及最基础的概念介绍), ...

随机推荐

  1. PHP 中的对象传递

    <?php class A { public $age = 0; public $username = ""; public $obj = null; } $a = new ...

  2. Java中 @Override 的作用

    @Override是伪代码,表示重写(当然不写也可以),不过写上有如下好处: 可以当注释用,方便阅读: 编译器可以给你验证@Override下面的方法名是否是你父类中所有的,如果没有则报错.例如,你如 ...

  3. postman获取请求响应值

    获取所有请求响应代码  var data = JSON.parse(responseBody);    把data的data值设置到token中  postman.setEnvironmentVari ...

  4. jQuery .tmpl(), .template()学习资料小结

    昨晚无意中发现一个有趣的jQuery插件.tmpl(),其文档在这里.官方解释对该插件的说明:将匹配的第一个元素作为模板,render指定的数据,签名如下: .tmpl([data,][options ...

  5. C#连接Oracle数据库的方法(Oracle.DataAccess.Client也叫ODP.net)

    官方下载地址(ODP.net)(中文):http://www.oracle.com/technetwork/cn/topics/dotnet/downloads/index.html 官方下载地址(O ...

  6. 胖子哥的大数据之路(四)- VisualHBase功能需求框架

    一.引言 大数据在结构化数据存储方面的应用需求越来越明确,但是大数据环境下辅助开发工具的不完善,给数据库管理人员和开发人员带来的不变难以言表,基于此创建了开源项目VisualHBase,同时创建了Vi ...

  7. 术语-服务:BaaS

    ylbtech-术语-服务:BaaS BaaS(后端即服务:Backend as a Service)公司为移动应用开发者提供整合云后端的边界服务. 1.返回顶部 1. 中文名:后端即服务 外文名:B ...

  8. 杂项-分布式-EDAS:深度解析阿里云EDAS服务

    ylbtech-杂项-分布式-EDAS:深度解析阿里云EDAS服务 1.返回顶部 1. 深度解析阿里云EDAS服务 弹性伸缩 摘要: 第一种只适用于业务较少的情况,而在新业务不断增加的情况下,增加新应 ...

  9. ESXI 5.5加载 zabbix OVF 3.2.6操作

    如果是虚拟机安装ZABBIX,ZABBIX的前台WEB时间,是由虚拟机的BIOS时间决定的. 一. 1.去官方下载vmdk磁盘镜像 链接地址为https://sourceforge.net/proje ...

  10. Jquery阻断事件冒泡(转载)

    JQuery阻止事件冒泡 冒泡事件就是点击子节点,会向上触发父节点,祖先节点的点击事件. 我们在平时的开发过程中,肯定会遇到在一个div(这个div可以是元素)包裹一个div的情况,但是呢,在这两个d ...