【漫画】JAVA并发编程之并发模拟工具
原创声明:本文来源于公众号【胖滚猪学编程】,转载请注明出处。
上一节【漫画】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方法所以被阻塞等待,T1T2T3线程通过调用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<Runnable>(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、运行线程组,就可以输出我们的结果了
好了,今天就到这里了,又到了要跟大家说拜拜的时候了~
原创声明:本文来源于公众号【胖滚猪学编程】,转载请注明出处。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
开发函数计算的正确姿势——OCR 服务
简介 首先介绍下在本文出现的几个比较重要的概念: OCR(光学字符识别): 光学字符识别(Optical Character Recognition, OCR)是指对文本资料的图像文件进行分析识别处理,获取文字及版面信息的过程。亦即将图像中的文字进行识别,并以文本的形式返回。 Tesserocr: Tesserocr 是 python 的一个 OCR 识别库,但其实是对 tesseract 做的一层 python API 封装,所以它的核心是 tesseract。 函数计算(Function Compute): 函数计算是一个事件驱动的服务,通过函数计算,用户无需管理服务器等运行情况,只需编写代码并上传。函数计算准备计算资源,并以弹性伸缩的方式运行用户代码,而用户只需根据实际代码运行所消耗的资源进行付费。函数计算更多信息参考。 Funcrfat: Funcraft 是一个用于支持 Serverless 应用部署的工具,能帮助您便捷地管理函数计算、API 网关、日志服务等资源。它通过一个资源配置文件(template.yml),协助您进行开发、构建、部署操作。Fun 的更多文档参考。 备...
- 下一篇
手把手教你爬取天堂网1920*1080大图片(批量下载)——理论篇
/1 前言/ 平时我们要下载图片,要要一个一个点击下载是不是觉得很麻烦?那有没有更加简便的方法呢?答案是肯定的,这里我们以天堂网为例,批量下载天堂网的图片。 /2 项目准备工作/ 首先 我们第一步我们要安装一个pycham的软件。可以参考这篇文章:Python环境搭建—安利Python小白的Python和Pycharm安装详细教程。 天堂网的网址: https://www.ivsky.com/bizhi/1920x1080/ 我们需要下载几个库,怎么下载呢?打开pycharm,依次点击File,再点开Settings,如下图所示。 打开后会出现这个界面点击你的项目名字(project:(你的项目名字)),之后在project interpreter下,点击加号,而后下载我们需要的库,如下图所示。 本项目需要用到的是库是requests、lxml、fake_useragent,如下图所示。fake_useragent一般是没有的,需要通过下面的命令进行安装: pip install fake_useragent /3 项目实现/ 1. 导入需要的库(requests,lxml, fake...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS6,CentOS7官方镜像安装Oracle11G
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Windows10,CentOS7,CentOS8安装Nodejs环境
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Hadoop3单机部署,实现最简伪集群