首页
关于
留言
Search
1
红米 AX3000 (AX6) 路由器解锁 SSH 教程
6,676 阅读
2
网盘挂载程序sharelist美化教程
4,216 阅读
3
小米路由器 AX3600 开启SSH教程,官方固件即可安装 ShellClash开启科学上网
2,168 阅读
4
Oracle 甲骨文 ARM VPS 自动抢购脚本
1,819 阅读
5
编译带PassWall和SSR-plus插件的Openwrt系统
1,393 阅读
前端
Vue
React
后端
Java
Python
PHP
数据库
运维
杂谈
小程序
影视资源
登录
Search
标签搜索
Java
Linux
Mysql
IDEA
Debian
Docker
Springboot
CentOS
Cloudflare
Maven
JavaScript
SQL
Wordpress
宝塔
Nginx
Windows
MacBook
JS
CSS
Openwrt
William
累计撰写
144
篇文章
累计收到
702
条评论
首页
栏目
前端
Vue
React
后端
Java
Python
PHP
数据库
运维
杂谈
小程序
影视资源
页面
关于
留言
搜索到
1
篇与
的结果
2022-10-22
如何编写一套多线程的测试用例?
一、摘要很多时候,新开发的功能在上线之前,我们都会进行压力测试,以防上线之后,突然出现性能瓶颈或者出现线程安全问题。那么问题来了,如何进行压力测试呢?实践的手段有很多种,比如采用 jmeter 、fiddler、postman 等第三方工具,可以快速实现性能压力测试。当然除此之外,其实我们也利用 java 的多线程特性,完全可以自行编写一套多线程的压力测试。下面我们以 访问百度首页服务 为例,向大家演示一下,采用 java 的多线程特性,该如何编写并发测试。二、代码实践方案一说到多线程,大家可能想到的就是实例化一个Thread对象,然后启动它,就可以实现异步处理,以模拟100个用户同时请求百度首页为例,代码实践如下:public static void main(String[] args) throws InterruptedException { //模拟100个线程,同时请求百度首页 long start = System.currentTimeMillis(); final int threadNum = 100; final CountDownLatch countDownLatch = new CountDownLatch(threadNum); for (int i = 0; i < threadNum; i++) { final int threadCount = i + 1; new Thread(new Runnable() { @Override public void run() { System.out.println("thread " + threadCount + " start"); //访问百度首页 String url = "https://www.baidu.com"; String rs = HttpUtils.getUrl(url); System.out.println("thread " + threadCount + " run result:" + rs); System.out.println("thread " + threadCount + " final"); //执行完成之后,计数器减一 countDownLatch.countDown(); } }).start(); } //线程同步阻塞 countDownLatch.await(); System.out.println("执行耗时:" + (System.currentTimeMillis() - start) + "ms"); }实践过程非常简单,采用Thread + CountDownLatch组合,进行阻塞测试。但是实际上往往我们进行多线程模拟用户进行访问某个服务的时候,每个用户的请求参数是不一样的,这个时候我们应该如何更加真实的贴近用户实际请求去测试呢?请看下面这个方案!方案二实际上在多线程并发编程中,它还有一个完美搭档,那就是 队列,采用 多线程+队列 组合编程模型,可以实现带任务的异步处理,并且性能高效!下面我们还是以 访问百度首页服务 为例,采用 多线程+队列 组合模式来模拟 100 个用户总共发起了1000次访问百度首页,代码实践如下!public static void main(String[] args) throws InterruptedException { //将每个用户访问百度服务的请求参数,存入阻塞队列BlockingQueue中 BlockingQueue<String> queue = new LinkedBlockingQueue<>(); for (int i = 0; i < 1000; i++) { queue.put("https://www.baidu.com?paramKey=" + i); } //模拟100个线程,执行1000次请求访问百度 long start = System.currentTimeMillis(); final int threadNum = 100; final CountDownLatch countDownLatch = new CountDownLatch(threadNum); for (int i = 0; i < threadNum; i++) { final int threadCount = i + 1; new Thread(new Runnable() { @Override public void run() { System.out.println("thread " + threadCount + " start"); boolean over = false; while (!over) { String url = queue.poll(); if(Objects.nonNull(url)) { //发起请求 String result =HttpUtils.getUrl(url); System.out.println("thread " + threadCount + " run result:" + result); }else { //任务结束 over = true; System.out.println("thread " + threadCount + " final"); countDownLatch.countDown(); } } } }).start(); } countDownLatch.await(); System.out.println("执行耗时:" + (System.currentTimeMillis() - start) + "ms"); }当然,你还可以自由调整线程数,也可以采用 juc 包的线程池来实现多线程编程,改造逻辑如下:public static void main(String[] args) throws InterruptedException { //将每个用户访问百度服务的请求参数,存入阻塞队列BlockingQueue中 BlockingQueue<String> queue = new LinkedBlockingQueue<>(); for (int i = 0; i < 1000; i++) { queue.put("https://www.baidu.com?paramKey=" + i); } //模拟100个线程,执行1000次请求访问百度 long start = System.currentTimeMillis(); final int threadNum = 100; //线程计数器 final CountDownLatch countDownLatch = new CountDownLatch(threadNum); //执行线程池 ExecutorService fixedThreadPool = Executors.newFixedThreadPool(threadNum); for (int i = 0; i < threadNum; i++) { final int threadCount = i + 1; fixedThreadPool.execute(new Runnable() { @Override public void run() { System.out.println("thread " + threadCount + " start"); boolean over = false; while (!over) { String url = queue.poll(); if(Objects.nonNull(url)) { //发起请求 String result =HttpUtils.getUrl(url); System.out.println("thread " + threadCount + " run result:" + result); }else { //任务结束 over = true; System.out.println("thread " + threadCount + " final"); countDownLatch.countDown(); } } } }); } countDownLatch.await(); fixedThreadPool.shutdown(); System.out.println("执行耗时:" + (System.currentTimeMillis() - start) + "ms"); }其中 BlockingQueue 阻塞队列,支持线程数据共享,当一个线程把数据取出之后,另一个线程无法再取,最后的运行效果是一样的!
2022年10月22日
27 阅读
0 评论
0 点赞