上一节【漫画】JAVA并发编程三大Bug源头(可见性、原子性、有序性)我们聊了聊并发编程的三个bug源头,这还没开始进入并发世界,胖滚猪就遇到了难题。。

这个难题是所有初学者都会有的疑惑:没法复现那些理论知识告诉我们的bug。但是实际操练很重要,那么在本地开发环境,到底应该怎样模拟并发呢?

模拟并发工具大全

在本地模拟并发环境的方法有挺多的,比较热门的有以下几种,包括工具和代码:

1、Postman:Http请求模拟工具,可以设置发起N个请求(但不推荐,并不专业)

2、Apache Bench(AB):Apache 服务器的一个web压力测试工具,是一个命令行工具,可根据命令创建很多并发访问线程,模拟多个访问者同时对某一个URL地址进行访问。总体来说,ab工具小巧简单,上手学习较快,可以提供需要的基本性能指标;但是缺点就是没有图形化结果,不能监控。

3、Apache JMeter:Apache组织开发的基于Java的压力测试工具。功能相比AB会更加强大,尤其是有GUI图形化界面,这一点很爽。另外jmeter是一次完整的请求和返回;AB只是发出去请求,并不对返回做处理。如果你希望看到返回结果,那么也应该选择JMeter。

4、JAVA代码:包括CountDownLatch、CyclicBarrier等

我们主要说一下如何通过jmeter和代码来模拟并发环境,也推荐使用这两种方式。

CountDownLatch(等待多线程完成)

原创声明:本文来源于公众号【胖滚猪学编程】,转载请注明出处。

countDownLatch是在java1.5被引入,存在于java.util.cucurrent包下。

这个类能使一个线程等待其他线程各自执行完毕后再执行。

它是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。

如图所示,初始值cnt=3,线程A执行了await方法所以被阻塞等待,T1\T2\T3线程通过调用countDown,让计数器减一,直到cnt=0后,Thread A才恢复运行。换句话说就是,Thread A需要等待其他三个线程都执行完才能执行:

countDownLatch类中只提供了一个构造器:

//参数count为计数值

public CountDownLatch(int count) { };

countDownLatch类中有三个方法是最重要的:

//调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行

public void await() throws InterruptedException { };

//和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行

public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };

//将count值减1

public void countDown() { };

举例:需求是处理一个Excel,Excel有很多行数据,为了效率,我们可以使用多线程处理,但是处理完所有行数据后,需要通知到主线程。如果没有countDownLatch,那么效果是这样的,还没处理完呢你就说我结束了:

如果在主线程上加上countDownLatch,并且调用await()方法,那么主线程会被挂起,它会等待直到count值为0才继续执行:

static CountDownLatch countDownLatch = new CountDownLatch(100);

public static void main(String[] args) throws InterruptedException {

for (int i = 0; i < 100; i++) {

Thread thread = new Thread(() -> {

doWork();

countDownLatch.countDown();

});

thread.start();

}

countDownLatch.await();

System.out.println("处理完整个excel的结束时间"+System.currentTimeMillis());

}

public static void doWork(){

System.out.println("处理行数据,时间"+System.currentTimeMillis());

}

Thread thread = new Thread(() -> {

try {

countDownLatch.await();

} catch (InterruptedException e) {

e.printStackTrace();

}

doWork();

});

thread.start();

countDownLatch.countDown();

线程池

ExecutorService executorService = new ThreadPoolExecutor(100,

200, 60, TimeUnit.MINUTES, new ArrayBlockingQueue(20000), new ThreadFactory() {

@Override

public Thread newThread(Runnable r) {

return new Thread(r);

}

});

CyclicBarrier(同步屏障)

原创声明:本文来源于公众号【胖滚猪学编程】,转载请注明出处。

CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活。

如下图所示,一共4个线程A、B、C、D,它们到达屏障的顺序可能各不相同。当A、B、C到达栅栏后,由于没有满足总数【4】的要求,所以会一直等待,当线程D到达后,栅栏才会放行。

CyclicBarrier构造方法

//其参数表示屏障拦截的线程数量

public CyclicBarrier(int parties)

//多了回调函数

public CyclicBarrier(int parties, Runnable barrierAction)

主要方法如下

//调用await方法的线程告诉CyclicBarrier自己已经到达同步点,然后当前线程被阻塞。直到parties个参与线程调用了await方法,阻塞线程才会执行。

public int await()

//带超时时间参数

public int await(long timeout, TimeUnit unit)

//重置

public void reset()

根据这一特性,我们也可以用于并发模拟,如下代码就是模拟了5个线程并发执行:

private static CyclicBarrier cyclicBarrier = new CyclicBarrier(5);

public static void main(String[] args) throws InterruptedException {

ExecutorService executorService = ExecutorServiceUtils.getExecutor();

for (int i = 0; i < 20; i++) {

int finalI = i;

Thread.sleep(1000);

executorService.submit(() -> {

try {

doWork(finalI);

} catch (Exception e) {

e.printStackTrace();

}

});

//通过打印日志 得出它具有自动重置功能

log.info("Parties={} 等待中{}",cyclicBarrier.getParties(),cyclicBarrier.getNumberWaiting());

}

executorService.shutdown();

}

public static void doWork(Integer threadNum) throws Exception {

Thread.sleep(1000);

log.info("{} is ready", threadNum);

cyclicBarrier.await();

log.info("{} continue", threadNum);

}

CountDownLatch 和 CyclicBarrier 的主要区别:

1、CountDownLatch 主要用来解决一个线程等待多个线程的场景,可以类比旅游团团长要等待所有的游客到齐才能去下一个景点;

而CyclicBarrier 是一组线程之间互相等待,更像是几个驴友之间不离不弃。

2、CountDownLatch是减计数方式,而CyclicBarrier是加计数方式。

3、CountDownLatch 的计数器是不能循环利用的,也就是说一旦计数器减到 0,再有线程调用 await(),该线程会直接通过。

但CyclicBarrier 的计数器是可以循环利用的,而且具备自动重置的功能,一旦计数器减到 0 会自动重置到你设置的初始值。

4、除此之外,CyclicBarrier 还可以设置回调函数,可以说是功能丰富。而CountDownLatch不支持回调函数。

好了,现在再回到最开头那段无法复现的代码,我们用CyclicBarrier来改写一下,你就可以看到出现0的情况了。

另外还要说一点:即使是真正的并发执行了,出问题依旧是小概率事件,本人亲测运行了15次才出现0的结果。运气不好可能运行100次还是不会看到。不必太过于纠结这些哦!

JMeter工具

1、下载好后解压目录,配置环境变量,运行jmeter.bat即可

2、添加一个线程组:

3、配置线程组相关属性,主要是线程数量以及是否循环,这里我们设置并发线程数是50,执行完每个线程后不需要循环:

4、添加http请求,比如我们要测试/test接口的请求:

配置http ip\端口\编码格式等:

5、添加两个监听器、用于执行结束后查看图形结果和查看结果数:

6、运行线程组,就可以输出我们的结果了

好了,今天就到这里了,又到了要跟大家说拜拜的时候了~

原创声明:本文来源于公众号【胖滚猪学编程】,转载请注明出处。

漫画编程java_【漫画】JAVA并发编程之并发模拟工具相关推荐

  1. aqs clh java_【Java并发编程实战】—– AQS(四):CLH同步队列

    在[Java并发编程实战]-–"J.U.C":CLH队列锁提过,AQS里面的CLH队列是CLH同步锁的一种变形. 其主要从双方面进行了改造:节点的结构与节点等待机制.在结构上引入了 ...

  2. Java并发编程的艺术-Java并发编程基础

    第4章 Java并发编程基础 ​ Java从诞生开始就明智地选择了内置对多线程的支持,这使得Java语言相比同一时期的其他语言具有明显的优势.线程作为操作系统调度的最小单元,多个线程能够同时执行,这将 ...

  3. phaser java_【Java并发编程实战】-----“J.U.C”:Phaser

    Phaser由java7中推出,是Java SE 7中新增的一个使用同步工具,在功能上面它与CyclicBarrier.CountDownLatch有些重叠,但是它提供了更加灵活.强大的用法. Cyc ...

  4. java任何封闭实例都不是java_《java并发编程实战》读书笔记3--对象的组合

    希望将一些现有的线程安全组件组合为更大规模的组件或程序 设计线程安全的类 如果对象中所有的域是基本类型变量,那么这些域将构成对象的全部状态.例如,LinkedList的状态就包括该链表中所有节点对象的 ...

  5. aqs clh java_【Java并发编程实战】----- AQS(一):简介

    在前面博客中,LZ讲到了ReentrantLock.ReentrantReadWriteLock.Semaphore.CountDownLatch,他们都有各自获取锁的方法,同时相对于Java的内置锁 ...

  6. Java并发编程实战_[Java并发编程实战] 简介

    并发简史 在早期不包含操作系统的计算机中,程序都是单一的串行程序,从头至尾只能执行一个程序,并且这个程序访问这个计算机的所有资源.然而,随着技术的发展,操作系统出现了.它使得计算机程序有了进程,线程的 ...

  7. java硬件编程_关于JAVA并发编程你需要知道的——硬件篇

    无论程序语言如何千变万化,他们都深深地根植于目前的计算机体系结构. 左图是intel CPU的三级高速缓存设计,由于高速缓存对程序员基本不可见,因此可以抽象为右图. 缓存的设计 首先还是先谈谈左图. ...

  8. Java并发编程—常见面试题

    建议: 学习java并发前需要先掌握JVM知识 关于下面问题档案的详细解析都在后面推荐的相关系列文章中 一.线程安全相关 1.什么叫线程安全? 线程安全就是说多线程访问同一代码,不会产生不确定的结果. ...

  9. Java并发编程系列

    Java并发编程系列 2018-03-08 Java 并发编程:核心理论 Java并发编程:Synchronized及其实现原理 Java并发编程:Synchronized底层优化(轻量级锁.偏向锁) ...

  10. 我肝了2个月,为你整理了Java并发编程手册

    从原理到实战,全面讲解Java并发编程核心知识,你值得拥有的Java并发编程手册. 如何看待程序员35岁职业危机? Java全套学习资料(14W字),耗时半年整理 我肝了三个月,为你写出了GO核心手册 ...

最新文章

  1. 香港中文大学(深圳)吴保元教授课题组招收全奖PhD、实习/访问学生
  2. 强弱AI的辩论:关于人工智能意识的奇妙理论
  3. java juc exchanger_JUC工具类实例
  4. java.text._Java.text
  5. python exe运行报 编码错误_python运行显示编码错误
  6. 使用Postgrest快速创建数据库的OpenAPI接口
  7. 亲爱的,你是最棒的!
  8. linux 线程管理、同步机制等
  9. python入门小游戏之跳一跳_从零基础开始,用python手把手教你玩跳一跳小游戏,直接打出高分...
  10. 荔枝图床阿里掘金搜狗奇虎图床源码
  11. idea的英文是什么意思_德芙和多芬的英文都是Dove!“Dove”究竟是什么意思?
  12. 第一公会强势分析《TmoLand》快速回本玩法
  13. MyEclipse从数据库反向生成实体类通过Hibernate的方式----mysql数据库实例
  14. 灵山奇缘服务器维护,灵山奇缘1月8日更新了什么 灵山奇缘1月8日更新维护内容一览...
  15. Python爬虫开发【第1篇】【urllib2】
  16. 用计算机算标准曲线,标准曲线计算器官方版
  17. Android Studio ADB 命令大全
  18. 小米 OJ 编程比赛 02 月常规赛 (Carryon 数数字)
  19. JAVA中成员变量和局部变量区别
  20. Deepin 深度技术 Windows XP SP2 珍藏版

热门文章

  1. 深信服防火墙console波特率_深信服防火墙AF上arp表数量限制导致网络问题的处理说明...
  2. Hadoop生态圈(六)- HDFS NAMENODE 安全模式
  3. python编程—猜数字小游戏
  4. Python txt文件转成xlsx文件
  5. 泰坦尼克号生存率分析
  6. X86架构CPU常识(主频,外频,FSB,cpu位和字长,倍频系数,缓存,CPU扩展指令集,CPU内核和I/O工作电压,制造工艺,指令集,超流水线与超标量)...
  7. Shiro内部过滤器执行顺序
  8. .NET Framework 3.5弹出错误代码0x800f0954解决方法
  9. C# 网络斗地主源码开源
  10. 关于地产信息化“大佬”们说了什么?看完这些就够了